diff --git a/.travis.yml b/.travis.yml index 729ad08c2c1..98d5f989f74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,4 +11,8 @@ install: - npm install gitbook-cli -g - gitbook install -script: gitbook build \ No newline at end of file +script: gitbook build + +branches: + except: + - crowdin_master diff --git a/am-ET/GLOSSARY.md b/am-ET/GLOSSARY.md new file mode 100644 index 00000000000..7f93ea7643a --- /dev/null +++ b/am-ET/GLOSSARY.md @@ -0,0 +1,3 @@ +# code editor + +''ኮድ አስተካካይ ማለት ምልክቶችን ለኋላ ጥቅም ለማዋል የሚረዳ መተግበሪያ ነው''. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/am-ET/README.md b/am-ET/README.md new file mode 100644 index 00000000000..121da8f55bf --- /dev/null +++ b/am-ET/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Introduction + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/am-ET/SUMMARY.md b/am-ET/SUMMARY.md new file mode 100644 index 00000000000..d9741b4f21c --- /dev/null +++ b/am-ET/SUMMARY.md @@ -0,0 +1,35 @@ +# Summary + +* [Introduction](README.md) +* [Installation](installation/README.md) + * [Command Line](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Code Editor](installation/README.md#code-editor) + * [Virtual Environment](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Installation (chromebook)](chromebook_setup/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) +* [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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/am-ET/chromebook_setup/README.md b/am-ET/chromebook_setup/README.md new file mode 100644 index 00000000000..03249a84d41 --- /dev/null +++ b/am-ET/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook setup + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/am-ET/chromebook_setup/instructions.md b/am-ET/chromebook_setup/instructions.md new file mode 100644 index 00000000000..2df2048e6ec --- /dev/null +++ b/am-ET/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +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 IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Cloud IDE 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 the software. For the duration of the tutorial, cloud IDE 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 IDE sets up for you. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). You can choose one of the cloud IDEs, and follow the instruction of the cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Go to [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Sign up for an account +3. Click *New Server* and choose the Django app +4. Click Terminal button(on the left side of the window) + +Now you should see an interface with a sidebar, buttons at the left. Click "Terminal" button to open terminal window with prompt like this: + +{% filename %}Terminal{% endfilename %} + + $ + + +The terminal on the PaizaCloud Cloud IDE is prepared for your instructions. You can resize or maximize that window to make it a bit bigger. + +#### AWS Cloud9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + yourusername:~/workspace $ + + +This bottom area is your terminal. You can use the terminal to send instructions to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### 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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/am-ET/code_editor/README.md b/am-ET/code_editor/README.md new file mode 100644 index 00000000000..0a401fb1f52 --- /dev/null +++ b/am-ET/code_editor/README.md @@ -0,0 +1,11 @@ +# Code editor + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +You're about to write your first line of code, so it's time to download a code editor! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. The cloud IDE you chose (PaizaCloud Cloud IDE or AWS Cloud9) includes a code editor, and when you open a file in your IDE from the File menu, you will automatically be using the editor. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/am-ET/code_editor/instructions.md b/am-ET/code_editor/instructions.md new file mode 100644 index 00000000000..82fbac15aad --- /dev/null +++ b/am-ET/code_editor/instructions.md @@ -0,0 +1,37 @@ +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. + +## Visual Studio Code + +Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + +[Download it here](https://code.visualstudio.com/) + +## 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 and it's available for all operating systems. + +[Download it here](https://www.sublimetext.com/3) + +## Atom + +Atom is another popular editor. It's free, open-source and available for Windows, OS X and Linux. Atom is developed by [GitHub](https://github.com/). + +[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. :) \ No newline at end of file diff --git a/am-ET/css/README.md b/am-ET/css/README.md new file mode 100644 index 00000000000..5f99728790d --- /dev/null +++ b/am-ET/css/README.md @@ -0,0 +1,330 @@ +# 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 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? 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: https://getbootstrap.com/ + +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, open up your `.html` file in the code editor and add this to the `` section: + +{% 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. So go ahead, open your website and refresh the page. Here it is! + +![Figure 14.1](images/bootstrap1.png) + +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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +Django already knows where to find the static files for the built-in "admin" app. Now we 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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +But let's do at least a little. Maybe we could change the color of our headers? 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, h2 a { + color: #C25100; +} + +``` + +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element; the `h2 a` selector does the same thing for `h2` elements. 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 `#C25100`, which is a dark orange. Or you can put your own color here, but make sure it has good contrast against a white background! + +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 element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file in the code editor and add this line at the very beginning of it: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +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 be overriden by 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 static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/am-ET/deploy/README.md b/am-ET/deploy/README.md new file mode 100644 index 00000000000..cc2d165200c --- /dev/null +++ b/am-ET/deploy/README.md @@ -0,0 +1,246 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/am-ET/deploy/install_git.md b/am-ET/deploy/install_git.md new file mode 100644 index 00000000000..53fbe28d617 --- /dev/null +++ b/am-ET/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in word processor programs (e.g., Microsoft Word or LibreOffice Writer), but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for two: in the step where it asks to choose your editor, you should pick Nano, and in the step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/am-ET/deploy/signup_pythonanywhere.md b/am-ET/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..555e36731dd --- /dev/null +++ b/am-ET/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use it for hosting our site, live and on the Internet. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/am-ET/django/README.md b/am-ET/django/README.md new file mode 100644 index 00000000000..0f2c4ef30f6 --- /dev/null +++ b/am-ET/django/README.md @@ -0,0 +1,27 @@ +# What is Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/am-ET/django_admin/README.md b/am-ET/django_admin/README.md new file mode 100644 index 00000000000..156eae05654 --- /dev/null +++ b/am-ET/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/am-ET/django_forms/README.md b/am-ET/django_forms/README.md new file mode 100644 index 00000000000..68676f99fa5 --- /dev/null +++ b/am-ET/django_forms/README.md @@ -0,0 +1,479 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `
...
`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Security + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/am-ET/django_installation/README.md b/am-ET/django_installation/README.md new file mode 100644 index 00000000000..9b024008342 --- /dev/null +++ b/am-ET/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/am-ET/django_installation/instructions.md b/am-ET/django_installation/instructions.md new file mode 100644 index 00000000000..fc965146844 --- /dev/null +++ b/am-ET/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/am-ET/django_models/README.md b/am-ET/django_models/README.md new file mode 100644 index 00000000000..f2a68a8727f --- /dev/null +++ b/am-ET/django_models/README.md @@ -0,0 +1,201 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/am-ET/django_orm/README.md b/am-ET/django_orm/README.md new file mode 100644 index 00000000000..ffe309bd81e --- /dev/null +++ b/am-ET/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/am-ET/django_start_project/README.md b/am-ET/django_start_project/README.md new file mode 100644 index 00000000000..3767c62e17f --- /dev/null +++ b/am-ET/django_start_project/README.md @@ -0,0 +1,260 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/am-ET/django_templates/README.md b/am-ET/django_templates/README.md new file mode 100644 index 00000000000..db2d20c4d4e --- /dev/null +++ b/am-ET/django_templates/README.md @@ -0,0 +1,108 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/am-ET/django_urls/README.md b/am-ET/django_urls/README.md new file mode 100644 index 00000000000..d37a5e3c2fd --- /dev/null +++ b/am-ET/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/am-ET/django_views/README.md b/am-ET/django_views/README.md new file mode 100644 index 00000000000..ab271e0914f --- /dev/null +++ b/am-ET/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/am-ET/dynamic_data_in_templates/README.md b/am-ET/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..5a6ef017adf --- /dev/null +++ b/am-ET/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/am-ET/extend_your_application/README.md b/am-ET/extend_your_application/README.md new file mode 100644 index 00000000000..c70a2db97ff --- /dev/null +++ b/am-ET/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/am-ET/how_the_internet_works/README.md b/am-ET/how_the_internet_works/README.md new file mode 100644 index 00000000000..7b2c014c292 --- /dev/null +++ b/am-ET/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![Figure 1.2](images/internet_3.png) + +It is fascinating, isn't it? But 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - you send messages and you expect some response. 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 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, 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 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! \ No newline at end of file diff --git a/am-ET/html/README.md b/am-ET/html/README.md new file mode 100644 index 00000000000..27c81ea68be --- /dev/null +++ b/am-ET/html/README.md @@ -0,0 +1,227 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is 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 `TemplateDoesNotExist`, try to restart your server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +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 line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to GitHub + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% 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. + +{% 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: + +{% 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 %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/am-ET/installation/README.md b/am-ET/installation/README.md new file mode 100644 index 00000000000..b97592acbe8 --- /dev/null +++ b/am-ET/installation/README.md @@ -0,0 +1,68 @@ +# 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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. + +Good luck! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Installation + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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. \ No newline at end of file diff --git a/am-ET/intro_to_command_line/README.md b/am-ET/intro_to_command_line/README.md new file mode 100644 index 00000000000..b95191c95c8 --- /dev/null +++ b/am-ET/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Your first command (YAY!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/am-ET/intro_to_command_line/open_instructions.md b/am-ET/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/am-ET/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/am-ET/python_installation/README.md b/am-ET/python_installation/README.md new file mode 100644 index 00000000000..8470b71f1f4 --- /dev/null +++ b/am-ET/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/am-ET/python_installation/instructions.md b/am-ET/python_installation/instructions.md new file mode 100644 index 00000000000..592aafe0b5d --- /dev/null +++ b/am-ET/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 the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/am-ET/python_introduction/README.md b/am-ET/python_introduction/README.md new file mode 100644 index 00000000000..6b66f8b55c6 --- /dev/null +++ b/am-ET/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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. + +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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, type the `exit()` function + +{% 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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/am-ET/template_extending/README.md b/am-ET/template_extending/README.md new file mode 100644 index 00000000000..7f3697b7fd4 --- /dev/null +++ b/am-ET/template_extending/README.md @@ -0,0 +1,151 @@ +# Template extending + +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. + +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 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 + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/am-ET/whats_next/README.md b/am-ET/whats_next/README.md new file mode 100644 index 00000000000..97c41870d93 --- /dev/null +++ b/am-ET/whats_next/README.md @@ -0,0 +1,43 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](https://twitter.com/djangogirls) to stay up to date. + +### Can you recommend any further resources? + +Yes! There are a *lot* of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. + +#### Django + +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS and JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! \ No newline at end of file diff --git a/am/GLOSSARY.md b/am/GLOSSARY.md new file mode 100644 index 00000000000..2e928dda548 --- /dev/null +++ b/am/GLOSSARY.md @@ -0,0 +1,3 @@ +# code editor + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/am/README.md b/am/README.md new file mode 100644 index 00000000000..01736ae0502 --- /dev/null +++ b/am/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) + +## Introduction + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/am/SUMMARY.md b/am/SUMMARY.md new file mode 100644 index 00000000000..7a45700a27d --- /dev/null +++ b/am/SUMMARY.md @@ -0,0 +1,27 @@ +# Summary + +* [Introduction](README.md) +* [Installation](installation/README.md) +* [Installation (chromebook)](chromebook_setup/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) +* [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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/am/chromebook_setup/README.md b/am/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/am/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/am/chromebook_setup/instructions.md b/am/chromebook_setup/instructions.md new file mode 100644 index 00000000000..809281456d3 --- /dev/null +++ b/am/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/am/code_editor/README.md b/am/code_editor/README.md new file mode 100644 index 00000000000..404011f1b7d --- /dev/null +++ b/am/code_editor/README.md @@ -0,0 +1,11 @@ +# Code editor + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +You're about to write your first line of code, so it's time to download a code editor! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/am/code_editor/instructions.md b/am/code_editor/instructions.md new file mode 100644 index 00000000000..074cd86196e --- /dev/null +++ b/am/code_editor/instructions.md @@ -0,0 +1,31 @@ +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 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 and 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. :) \ No newline at end of file diff --git a/am/css/README.md b/am/css/README.md new file mode 100644 index 00000000000..04d5996ae52 --- /dev/null +++ b/am/css/README.md @@ -0,0 +1,304 @@ +# 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 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? 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: https://getbootstrap.com/ + +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: + +{% 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! + +![Figure 14.1](images/bootstrap1.png) + +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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +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. 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 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 + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +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. :) 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 be overriden by 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 %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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 + +``` + +And now add a class `post` to your `div` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/am/deploy/README.md b/am/deploy/README.md new file mode 100644 index 00000000000..b44e2eaaf73 --- /dev/null +++ b/am/deploy/README.md @@ -0,0 +1,260 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ 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) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. + +Hit **Save** and then go back to the **Web** tab. + +We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. + +## Debugging tips + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: + +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. + +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. + +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? + +- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. + +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +And remember, your coach is here to help! + +# You are live! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! \ No newline at end of file diff --git a/am/deploy/install_git.md b/am/deploy/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/am/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/am/deploy/signup_pythonanywhere.md b/am/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/am/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/am/django/README.md b/am/django/README.md new file mode 100644 index 00000000000..c62c145305b --- /dev/null +++ b/am/django/README.md @@ -0,0 +1,27 @@ +# What is Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +Of course, the description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will simply start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/am/django_admin/README.md b/am/django_admin/README.md new file mode 100644 index 00000000000..46a5afbb500 --- /dev/null +++ b/am/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/am/django_forms/README.md b/am/django_forms/README.md new file mode 100644 index 00000000000..1d9efebffe4 --- /dev/null +++ b/am/django_forms/README.md @@ -0,0 +1,447 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? + +## URL + +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```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` we add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## Security + +Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to Github: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/am/django_installation/README.md b/am/django_installation/README.md new file mode 100644 index 00000000000..7834993e063 --- /dev/null +++ b/am/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/am/django_installation/instructions.md b/am/django_installation/instructions.md new file mode 100644 index 00000000000..0bc080f7055 --- /dev/null +++ b/am/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/am/django_models/README.md b/am/django_models/README.md new file mode 100644 index 00000000000..7aa11d11732 --- /dev/null +++ b/am/django_models/README.md @@ -0,0 +1,199 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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 + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/am/django_orm/README.md b/am/django_orm/README.md new file mode 100644 index 00000000000..31c47f27764 --- /dev/null +++ b/am/django_orm/README.md @@ -0,0 +1,218 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Chaining QuerySets + +You can also combine QuerySets by **chaining** them together: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/am/django_start_project/README.md b/am/django_start_project/README.md new file mode 100644 index 00000000000..fe1abc7ca9a --- /dev/null +++ b/am/django_start_project/README.md @@ -0,0 +1,202 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![It worked!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/am/django_templates/README.md b/am/django_templates/README.md new file mode 100644 index 00000000000..263eb1fd835 --- /dev/null +++ b/am/django_templates/README.md @@ -0,0 +1,106 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/am/django_urls/README.md b/am/django_urls/README.md new file mode 100644 index 00000000000..c491b27de5c --- /dev/null +++ b/am/django_urls/README.md @@ -0,0 +1,129 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![Url](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Regex + +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. + +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: + +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern + +Anything else in the URL definition will be taken literally. + +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. + +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: + +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/am/django_views/README.md b/am/django_views/README.md new file mode 100644 index 00000000000..07afe091a52 --- /dev/null +++ b/am/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/am/dynamic_data_in_templates/README.md b/am/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..807bb666ebc --- /dev/null +++ b/am/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/am/extend_your_application/README.md b/am/extend_your_application/README.md new file mode 100644 index 00000000000..0bae760be7c --- /dev/null +++ b/am/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: + +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? Of course: adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`. + +It will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ 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 %} + +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 --all . + $ git status + $ 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/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/am/how_the_internet_works/README.md b/am/how_the_internet_works/README.md new file mode 100644 index 00000000000..efd95c3f4b2 --- /dev/null +++ b/am/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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. + +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![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 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - 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 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, 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 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! \ No newline at end of file diff --git a/am/html/README.md b/am/html/README.md new file mode 100644 index 00000000000..004985089c2 --- /dev/null +++ b/am/html/README.md @@ -0,0 +1,213 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Add the following to your template file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +

Hi there!

+

It works!

+ +``` + +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 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `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, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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.

+
+ + +``` + +We've created three `div` sections here. + +* 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to Github + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% 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: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **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): + +{% 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. + +{% 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: + +{% 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 + $ git pull + [...] + + +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. + +* 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. :) \ No newline at end of file diff --git a/am/install_git.md b/am/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/am/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/am/installation/README.md b/am/installation/README.md new file mode 100644 index 00000000000..a7c627136c8 --- /dev/null +++ b/am/installation/README.md @@ -0,0 +1,58 @@ +# 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 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. \ No newline at end of file diff --git a/am/instructions.md b/am/instructions.md new file mode 100644 index 00000000000..30bd493b11b --- /dev/null +++ b/am/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/am/intro_to_command_line/README.md b/am/intro_to_command_line/README.md new file mode 100644 index 00000000000..5fb6d48dd1f --- /dev/null +++ b/am/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +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. :) + +> 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 by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/am/python_installation/README.md b/am/python_installation/README.md new file mode 100644 index 00000000000..93f81cb42d9 --- /dev/null +++ b/am/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/am/python_installation/instructions.md b/am/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/am/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/am/python_introduction/README.md b/am/python_introduction/README.md new file mode 100644 index 00000000000..c1642302532 --- /dev/null +++ b/am/python_introduction/README.md @@ -0,0 +1,1062 @@ +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.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. + +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. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, simply type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% 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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% 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! + +{% 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% 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 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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 + +{% 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!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/am/signup_pythonanywhere.md b/am/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/am/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/am/template_extending/README.md b/am/template_extending/README.md new file mode 100644 index 00000000000..35997f913d3 --- /dev/null +++ b/am/template_extending/README.md @@ -0,0 +1,147 @@ +# Template extending + +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. + +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 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 + + +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 %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. 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' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/am/whats_next/README.md b/am/whats_next/README.md new file mode 100644 index 00000000000..fbb1d2a7d6e --- /dev/null +++ b/am/whats_next/README.md @@ -0,0 +1,25 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](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](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). + +Later on, you can try the resources listed below. They're all very recommended! + +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/ar-SA/GLOSSARY.md b/ar-SA/GLOSSARY.md new file mode 100644 index 00000000000..5857b137396 --- /dev/null +++ b/ar-SA/GLOSSARY.md @@ -0,0 +1,3 @@ +# محرر الكود + +محرر الكود هو التطبيق الذي يسمح لك بحفظ التعليمات البرمجية الخاصة بك بحيث تكون قادر على العودة إليها في وقت لاحق. ويمكنك معرفة أين يمكن الحصول على واحد من الفصل الخاص [بمحرر الكود](./code_editor/README.md) \ No newline at end of file diff --git a/ar-SA/README.md b/ar-SA/README.md new file mode 100644 index 00000000000..76bf2808dc3 --- /dev/null +++ b/ar-SA/README.md @@ -0,0 +1,51 @@ +# الدليل التطبيقي Django Girls + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> تم ترخيص هذا العمل تحت نَسب المُصنَّف - غير تجاري - الترخيص بالمثل 4.0 بموجب ترخيص المشاع الإبداعي الدولي. لعرض نسخة من هذا الترخيص، تفضلوا بزيارة https://creativecommons.org/licenses/by-sa/4.0/ + +## مرحباً + +مرحبا بكم في الدليل التطبيقي Django Girls! يسعدنا رؤيتك هنا. :) في هذا الدليل التطبيقي ، سوف نأخذك في رحلة تحت سقف تقنيات الشبكة ، وسنقوم بإعطائك لمحة عن كل الأجزاء والقطع التي تحتاج أن تعمل معاً من أجل أن تعمل الشبكة العنكبوتية كما نعرفها. + +كما هو الحال مع كل الأشياء التي لا نعرفها ، هذه ستكون مغامرة - لكن لا داعي للقلق ، بما أنك استجمعت قوتك وأتيت إلى هنا ، سوف تكون على ما يرام. :) + +## المقدمة + +هل سبق وشعرتم بأن العالم يدور حول التقنية التي لم تستطيعون (حتى الآن) فهمها؟ هل تسائلتم كيف يمكن إنشاء موقع على شبكة الإنترنت ولكن لم يكن لديكم الدافع الكافي للبدء؟ هل فكرتم يوما أن عالم البرمجيات معقد للغاية لدرجة أنكم لن تتمكنون حتى من تجربة ذلك بأنفسكم؟ + +حسناً، لدينا أخبار جيدة لكم! البرمجة ليست بتلك الصعوبة التي تتصورونها وسنريكم كيف تكون ممتعة. + +هذا الدليل لن يحولكم لمبرمجات بطريقة سحرية. إذا كنتم تريدون التميز في البرمجة، فلابد من الاستمرار بالتعلم والممارسة لأشهر أو سنوات. ولكننا نريد أن نظهر لكم أن البرمجة أو بناء المواقع الإلكترونية ليس بتلك الصعوبة. سنحاول شرح مختلف الاجزاء، بكل وسعنا، حتى لا تتخوفون من التقنية. + +ونأمل أن نجعلكم تحبون التقنية بقدر ما نحبها نحن! + +## ماذا ستتعلمون خلال هذا الدليل التطبيقي؟ + +بمجرد الانتهاء من الدليل التطبيقي، سيكون لديكم تطبيق ويب: مدونتكم الخاصة. سنشرح لكم كيف يمكنكم نشرها، بحيث يمكن للآخرين الاطلاع عليها! + +ستبدو مدونتكم شبيهة إلى حد كبير بهذه الصورة: + +![الرقم 0.1](images/application.png) + +> إذا كنتم تعملون بمفردكم، وليس لديكم مرشدين لمساعدتكم في حالة وجود أي مشكلة أثناء التطبيق، فلدينا نظام محادثة لكم: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). لقد طلبنا من مرشداتنا ومن حضروا سابقاً للتواجد في نظام المحادثة من وقت لآخر لتقديم المساعدة لمن يحتاجها! لا تترددون في طرح سؤالكم هنا! + +حسنا، [ لنبدأ من البداية... ](./how_the_internet_works/README.md) + +## اتباع الدليل التطبيقي في المنزل + +من الرائع أن تحضرون مقر ورشة عمل Django Girls، لكننا نتفهم أنه قد لا يمكنكم حضورها. لذلك نشجعكم على محاولة اتباع هذا الدليل التطبيقي في المنزل. للقراء في المنزل، نعد حاليا مقاطع فيديو نأمل أن تجعل رحلتكم في التطبيق أسهل. ما زلنا نعمل عليها، لكن ستكون التحديثات متوفرة قريباً في قناة يوتيوب [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed). + +في كل فصل تم تغطيته، هناك ارتباط يشير إلى الفيديو الصحيح. + +## عن Django Girls والمساهمة + +هذا الدليل التعليمي يدار بواسطة [DjangoGirls](https://djangogirls.org/). إذا وجدتم أي خطأ أو رغبتم في تحديث الدليل التطبيقي يرجى [اتباع المبادئ التوجيهية للمساهمة](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## هل تريدون مساعدتنا في ترجمة الدليل التطبيقي إلى لغات أخرى؟ + +حاليا، يجري الاحتفاظ بالترجمات على منصة crowdin.com في: + +https://crowdin.com/project/django-girls-tutorial + +إذا لم تكن لغتكم موجودة في [crowdin](https://crowdin.com/)، فنرجو منكم [إنشاء طلب](https://github.com/DjangoGirls/tutorial/issues/new) لإضافتها. \ No newline at end of file diff --git a/ar-SA/SUMMARY.md b/ar-SA/SUMMARY.md new file mode 100644 index 00000000000..819c808e85a --- /dev/null +++ b/ar-SA/SUMMARY.md @@ -0,0 +1,35 @@ +# الملخص + +* [المقدمة](README.md) +* [التثبيت](installation/README.md) + * [سطر الأوامر](installation/README.md#command-line) + * [بايثون](installation/README.md#python) + * [محرر الكود](installation/README.md#code-editor) + * [البيئة الإفتراضية](installation/README.md#virtualenv) + * [جانغو](installation/README.md#django) + * [جيت (Git)](installation/README.md#git) + * [جيتهاب (GitHub)](installation/README.md#github-account) + * [بايثون في كل مكان](installation/README.md#pythonanywhere-account) +* [التثبيت (كروم بوك)](chromebook_setup/README.md) +* [كيف يعمل الإنترنت](how_the_internet_works/README.md) +* [مقدمة لسطر الأوامر](intro_to_command_line/README.md) +* [تركيب بايثون](python_installation/README.md) +* [محرر الكود](code_editor/README.md) +* [مقدمة إلى بايثون](python_introduction/README.md) +* [ما هو جانغو؟](django/README.md) +* [تركيب جانغو](django_installation/README.md) +* [مشروعك الأول في جانغو!](django_start_project/README.md) +* [نماذج جانغو](django_models/README.md) +* [مشرف جانغو](django_admin/README.md) +* [الإعداد!](deploy/README.md) +* [روابط جانغو](django_urls/README.md) +* [واجهات جانغو - وقت الإنشاء!](django_views/README.md) +* [مقدمة إلى HTML](html/README.md) +* [ORM جانغو (Querysets)](django_orm/README.md) +* [البيانات الديناميكية في القوالب](dynamic_data_in_templates/README.md) +* [قوالب جانغو](django_templates/README.md) +* [إجعله جميلا بإستخدام CSS](css/README.md) +* [تمديد القالب](template_extending/README.md) +* [توسيع التطبيق الخاص بك](extend_your_application/README.md) +* [نماذج جانغو](django_forms/README.md) +* [ما هي الخطوة التالية؟](whats_next/README.md) \ No newline at end of file diff --git a/ar-SA/chromebook_setup/README.md b/ar-SA/chromebook_setup/README.md new file mode 100644 index 00000000000..e72101085fe --- /dev/null +++ b/ar-SA/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# إعداد جهاز كروم بوك + +> **ملاحظة** اذا كنت قد مررت من هذه المرحلة من قبل ، لا تحتاج للقيام بذلك مرة أخرى--يمكنك تخطي هذه المرحلة والإنتقال إلى [مقدمة بايثون](../python_introduction/README.md). + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/ar-SA/chromebook_setup/instructions.md b/ar-SA/chromebook_setup/instructions.md new file mode 100644 index 00000000000..bd807d529f8 --- /dev/null +++ b/ar-SA/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +يمكنك [تخطي هذا القسم ](http://tutorial.djangogirls.org/en/installation/#install-python) إذا كنت لا تستخدم كروم بوك. إذا كنت كذلك، تجربة التثبيت الخاص بك سوف تكون مختلفة قليلاً. يمكنك تجاهل بقية إرشادات التثبيت. + +### بيئة التطوير المتكاملة السحابية (PaizaCloud Cloud IDE, AWS Cloud9) + +بيئة التطوير المتكاملة السحابية هي أداة توفر لك تحرير الأكواد البرمجية والوصول إلى جهاز كمبيوتر يعمل على شبكة الإنترنت حيث يمكنك تثبيت، وكتابة، وتشغيل البرامج. خلال مدة البرنامج التعليمي، بيئة التطوير المتكاملة السحابية ستكون بمثابة *الجهاز المحلي* الخاص بك. سوف تقوم بتنفيذ الأوامر في موجه الأوامر مثل زملائك الذين يعملون على أنظمة OS X, Ubuntu, أو Windows, لكن موجه الأوامر في السحابة سيكون متصل بجهاز حاسوبي يعمل في مكان اخر تقوم بيئة التطوير المتكاملة السحابية بإعداده لك. وإليك الإرشادات الخاصة ببيئات التطوير المتكاملة السحابية (PaizaCloud Cloud IDE, AWS Cloud9). يمكنك اختيار إحدى بيئات التطوير المتكاملة السحابية، واتباع تعليمات بيئة التطوير المتكاملة السحابية. + +#### بيئة التطوير المتكاملة السحابية PaizaCloud + +1. الذهاب إلى [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. إنشاء حساب جديد +3. إنشاء خادم بالضغط على *New Server* واختيار Django +4. الضغط على زر Terminal (على الجانب الأيسر من النافذة) + +الآن سترى واجهة مع قائمة جانبية، وأزرار على اليسار. اضغطي زر "Terminal" لفتح نافذة موجه الأوامر مثل هذا: + +{% filename %} Terminal{% endfilename %} + + $ + + +موجه الأوامر في PaizaCloud IDE مستعد لأوامرك. يمكنك تغيير حجم النافذة أو تكبيرها لجعلها أكبر قليلاً. + +#### AWS Cloud9 + +حالياً Cloud 9 تتطلب تسجيلك في AWS وإدخال معلومات بطاقتك البنكية. + +1. ثبت Cloud 9 من [ متجر كروم](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. إذهب الى [c9.io](https://c9.io) واضغط على *Get started with AWS Cloud9* +3. أنشئ حساب في AWS (يتطلب معلومات بطاقتك البنكية، لكن تستطيع استخدامها مجاناً) +4. من AWS Dashboard، أدخل *Cloud9* في مربع البحث ثم اضغطه +5. من Cloud 9 dashboard، اضغط *Create environment* +6. سمه *django-girls* +7. أثناء تعديل الإعدادات، من "Environment Type" اختر *Create a new instance for environment (EC2)*، ومن "Instance type" اختر *t2.micro*. (المفترض يظهر لك "Free-tier eligible." أي أنها متوفرة في الفئة المجانية). إعدادات cost-saving الافتراضية لا بأس بها، وتستطيع إبقاء الإعدادات الافتراضية الأخرى على ما هي عليه. +8. اضغط على *Next step* +9. اضغط *Create environment* + +الآن يفترض أن تشاهد واجهة وقائمة جانبية، ونافذة رئيسية كبيرة تحتوي نص، ونافذة صغيرة في الجزء السفلي التي تبدو مثل هذا: + +{% filename %}bash{% endfilename %} + + yourusername:~/workspace $ + + +هذه المساحة السفلية تحتوي موجه الأوامر الخاص بك. يمكنك استخدام موجه الأوامر لإرسال التعليمات إلى الكمبيوتر البعيد في Cloud 9. يمكنك تغيير حجم تلك النافذة لجعلها أكبر قليلاً. + +#### معرف Glitch.com السحابي + +1. انتقل إلى [Glitch.com](https://glitch.com/) +2. قم بالتسجيل للحصول على حساب (https://glitch.com/signup) أو استخدم حساب GitHub الخاص بك إذا كان لديك حساب. (انظر تعليمات GitHub أدناه) +3. انقر فوق *New Project* واختر *hello-webpage* +4. انقر على قائمة الأدوات المنسدلة (في الجزء السفلي الأيسر من النافذة)، ثم على زر المحطة الطرفية لفتح علامة التبويب الطرفية مع توجيه مثل هذا: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +عند استخدام Glitch.com كقاعدة بيانات سحابية، لا تحتاج إلى إنشاء بيئة افتراضية. بدلاً من ذلك، قم بإنشاء الملفات التالية يدوياً: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +بمجرد إنشاء هذه الملفات، انتقل إلى المحطة الطرفية وتنفيذ الأوامر التالية لإنشاء أول مشروع جانغو الخاص بك: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + قم بالتحديث + + +من أجل رؤية رسائل الخطأ المفصلة، يمكنك تفعيل سجلات التصحيح جانغو لتطبيق Glitch الخاص بك. ببساطة إضافة ما يلي في نهاية ملف `mysite/settings.py`. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +سيؤدي هذا إلى إنشاء `debug.log` ملف يفصل عمليات جانغو وأي رسائل خطأ قد تظهر، يجعل من الأسهل إصلاح ما إذا كان موقع الويب الخاص بك لا يعمل. + +يجب أن تفشل عملية إعادة التشغيل الأولية لمشروع Glitch. (إذا قمت بالنقر على زر القائمة المنسدلة العلوية `Show` وبعدها على `In a New Window`، سوف تتلقى رسالة خطأ `DisallowedHost` .) لا تقلق بشأن ذلك في هذه المرحلة، هذا البرنامج التعليمي سوف يصلح هذا بمجرد أن تحدث إعدادات جانغو للمشروع الخاص بك في ملف `mysite/settings.py`. + +### البيئة الافتراضية + +البيئة افتراضية (وتسمى أيضا virtualenv) مثل صندوق خاص يمكننا ملئه بأكواد برمجية مفيدة من اجل مشروع نعمل عليه. نستخدم البيئة الإفتراضية لنحافظ على الأكواد البرمجية التي نريدها لمشاريع مختلفة في بيئات منفصلة، حتى لا تختلط مع مشاريع اخرى. + +تشغيل: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(لاحظ أنه بالسطر الأخير إستخدمنا علامة المد تليها علامة يساوي: `~=`). + +### GitHub + +أنشئ حساب في [GitHub](https://github.com). + +### بايثون في كل مكان + +يتضمن البرنامج التعليمي للفتيات في جانغو قسما عما يسمى بالنشر، وهي عملية أخذ التعليمات البرمجية التي تعمل على تطبيق الويب الجديد ونقلها إلى جهاز كمبيوتر متاح للجمهور (يسمى الخادم) حتى يتمكن أشخاص آخرين من رؤية عملك. + +هذا الجزء غريب نوعاً ما عند تنفيذ البرنامج التعليمي على جهاز كروم بوك لأننا نستخدم جهاز كمبيوتر موجود على الإنترنت أساساً (ليس مثل أي كمبيوتر محمول آخر). ومع ذلك، فإنه لا يزال مفيدا، إذا فكرنا في مساحة عمل Cloud 9 كمكان لعملنا "تحت الإنشاء" و Python Anywhere كمكان لعرض أشيائنا إذا اكتملت. + +بالتالي، قم بتسجيل حساب جديد في Python Anywhere عبر هذا الرابط [www.pythonanywhere.com](https://www.pythonanywhere.com). \ No newline at end of file diff --git a/ar-SA/code_editor/README.md b/ar-SA/code_editor/README.md new file mode 100644 index 00000000000..b17536a4faa --- /dev/null +++ b/ar-SA/code_editor/README.md @@ -0,0 +1,11 @@ +# محرر الكود + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [تثبيت بايثون & محرر التعليمات البرمجية](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s). + +أنت على وشك كتابة أول سطر كود خاص بك، لذا حمل برنامج محرر الكود! + +> **ملاحظة** إذا كنت تستخدم كروم بوك، تخطي هذا الفصل وتأكد من اتباع [تعليمات إعداد كروم بوك](../chromebook_setup/README.md). بيئة التطوير المتكاملة IDE السحابية التي اخترتها (PaizaCloud Cloud IDE or AWS Cloud9) تحتوي على محرر أكواد، وعندما تفتح ملف في بيئة التطوير خاصتك عن طريق قائمة ملف، سوف تقوم تلقائياً باستخدام المحرر. +> +> **لاحظ** ربما فعلت ذلك في وقت سابق في [فصل التثبيت](../installation/README.md) - إذا كان الأمر كذلك يمكنك التخطي مباشرة إلى الفصل التالي! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/ar-SA/code_editor/instructions.md b/ar-SA/code_editor/instructions.md new file mode 100644 index 00000000000..286bccd5df5 --- /dev/null +++ b/ar-SA/code_editor/instructions.md @@ -0,0 +1,37 @@ +يوجد العديد من برامج التحرير لكن الخيار الاخير يعود للشخص. اغلب مبرمجي البايثون يستخدمون بيئات تطوير متكاملة (IDEs) معقدة لكنها قوية مثل PyCharm. كمبتدئ على الأرجح هذا الخيار أقل ملائمة؛ نحن نوصي ببرامج قوية على نفس المستوى، ولكن أبسط بكثير. + +اقتراحاتنا مدرجة بالاسفل، لكن لا تتردد أن تسأل المدرب عن برنامجه المفضل - سوف يكون من الأسهل الحصول على مساعدة منهم. + +## Visual Studio Code + +Visual Studio Code هو محرر أكواد من مايكروسوفت لنظام Windows و Linux و macOS. ويشمل دعمًا للتصحيح، والتحكم في Git، وتمييز بناء الجملة، وإكمال الكود الذكي، واقتباس الأكواد، وتعديلها. + +[يمكنك تحميل البرنامج هنا](https://code.visualstudio.com/) + +## Gedit + +Gedit محرر أكواد مجاني، ومفتوح المصدر، ومتاح لجميع أنظمة التشغيل. + +[يمكنك تحميل البرنامج هنا](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text هو محرر شائع جدا مع فترة مجانية للتقييم، ومتاح لجميع أنظمة التشغيل. + +[يمكنك تحميل البرنامج هنا](https://www.sublimetext.com/3) + +## Atom + +Atom محرر أكواد آخر. مجاني، ومفتوح المصدر، ومتوفر لأنظمة Windows و OS X و Linux. تم تطويره من قبل [GitHub](https://github.com/). + +[يمكنك تحميل البرنامج هنا](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/ar-SA/css/README.md b/ar-SA/css/README.md new file mode 100644 index 00000000000..5b2592e39c2 --- /dev/null +++ b/ar-SA/css/README.md @@ -0,0 +1,330 @@ +# CSS – اجعل الأمر رائعاً! + +لا تزال مدونتنا تبدو قبيحة جداً، أليس كذلك؟ حان الوقت لجعلها جميلة! سنستخدم CSS لذلك. + +## ما هي تقنية CSS؟ + +CSS هي لغة تجميل المواقع, تخيل HTML هي هيكل المنزل يعني الحائط و السارية و السقف و CSS هي الصباغة و الصقل والديكور... و ما إلى ذلك , يعني مثل المكياج + +لكننا لا نريد أن نبدأ من الصفر مرة أخرى، أليس كذلك؟ مرة أخرى، سنستخدم شيئا خلقه المبرمجون على الإنترنت مجانا. إعادة اختراع العجلة ليس ممتعا، كما تعلمون. + +## لنستخدم Bootstrap! + +Bootstrap اطار عمل الأكثر شعبية لـ HTML و CSS لتطوير مواقع جميلة: https://getbootstrap.com/ + +كتب بواسطة المبرمجين الذين عملوا على تويتر والآن يتم تطويره من قبل المتطوعين من جميع أنحاء العالم! + +## تثبيت Bootstrap + +لتحميل Bootstrap ، افتح ملف `.html` خاصتك في محرر الكود وأضف هذا في جزء ``: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +هذا لا يضيف أي ملفات إلى المشروع الخاص بك. بل يشير فقط إلى الملفات الموجودة على شبكة الإنترنت. افتح موقع الويب الخاص بك وقم بتحديث الصفحة. لاحظت الفرق! + +![الرقم 14.1](images/bootstrap1.png) + +يبدو اجمل الان! + +## الملفات الثابتة في Django + +اخيراً سوف نمعن بالنظر على ما اسميناه **بالملفات الثابتة**. الملفات الثابتة هي كل CSS والصور. محتواهم لا يعتمد على خاصية الطلب وسيكون مشابها عند الجميع. + +### اين توضع الملفات الثابتة لمشروع Django + +جانغو عرف مسبقا أين يجد الملفات الثابتة للتطبيق المضمن "admin". الان لايلزمنا سوى اضافة بعض الملفات الثابتة للتطبيق الخاص بنا,`blog`. + +نقوم بذلك بانشاء مجلد نسميه `static` داخل تطبيق المدونة: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │ └── templates + └── mysite + + +جانغو سيجد تلقائيا أي مجلد باسم "static" داخل اي مجلد يحتويه تطبيقك. وسيستطيع استعمال محتوياته كملفات ثابتة. + +## الأن مع ملفات CSS + +لنقم بانشاء ملف نمطي CSS. لتظيف تعديلاتك الخاصة لموقعك. قم بانشاء مجلد باسم `css` داخل مجلد `static`. قم بانشاء ملف باسم `blog.css` داخل المجلد `css`. مستعد ؟ + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +حان الوقت للقيام بكتابة بعض CSS,قم بفتح الملف `blog/static/css/blog.css` داخل المحرر. + +لن نذهب عميقاً في تخصيص وتعلم CSS هنا. هناك توصية بدورة CSS مجانية في نهاية هذه الصفحة إذا كنت ترغب في معرفة المزيد. + +لكن لنقم بالقليل على الاقل. ربما نريد تغيير لون الترويسة؟ لفهم الالوان, الحاسوب يستعمل شيفرات خاصة. الشيفرات تبتدأ ب `#` و تليها 6 حروف (A-F) و أرقام (0-9). مثلا ، رمز اللون الأزرق هو `#0000FF`. يمكنك العثور على هذه الشيفرات في هذا الموقع: http://www.colorpicker.com/. يمكنك استعمال الالوان المحددة مسبقا ك `red` و `green`. + +داخل الملف `blog/static/css/blog.css` يجب عليك اضافة التعليمات البرمجية التالية: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1 a` هو محدد CSS. وهذا يعني أننا تقوم بتطبيق أنماط لدينا إلى أي عنصر من عناصر `a` داخل عنصر `h1`؛ محدد `h2 a` يفعل الشيء نفسه لعناصر `h2`. حتى عندما يكون لدينا شيء مثل `

link

`، `h1` سيتم تطبيق النمط. في هذه الحالة نأمرها بتغيير الون الى `#Fca205`, وهو اللون البرتقالي الداكن. أو يمكنك وضع اللون الذي تريده هنا، ولكن تأكد من تباين هذا اللون عن الخلفية البيضاء! + +داخل ملف CSS نحدد أنماط العناصر التي توجد داخل ملف HTML. الطريقة الأولى التي نستخدمها لتحديد العناصر هي عبر الإسم. يمكن أن تذكر هذه tags من قسم HTML. أشياء مثل`a`, `h1` و `body` هي كلها امثلة لأسماء العناصر. نحن نحدد العناصر ايضا عبر `class` او عبر `id`. Class و id هي الأسماء التي يمكنك إعطائها للعنصر بنفسك. تحدد class مجموعات من العناصر، و id تشير إلى عناصر محددة. على سبيل المثال، يمكنك تحديد العنصر التالي باستخدام اسم العنصر `a`، الفئة `external_link` أو المعرف `link_to_wiki_page`: + +```html + +``` + +اقرأ عن [محددات CSS في w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +نحن بحاجة إلى أن نقول أيضا لقالب HTML أننا أضفنا بعض ال CSS. افتح الملف `blog/templates/blog/post_list.html` في محرر الأكواد وأضف هذا السطر في البداية: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +نحن فقط نحمل الملفات الثابتة هنا ما بين علامات `` و `` بعد الارتباطات بملفات بوتستراب CSS ، قم بإضافة هذا السطر: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +المتصفح يقرأ الأوامر بالترتيب الذي اعطي له ، لذا يجب علينا التأكد من ان هذا في المكان الصحيح. وإلا فإن الكود في الملف الخاص بك قد يتم تجاوزه بواسطة الكود في ملفات بوتستراب. قمنا لتونا بإعلام القالب أين توجد ملفات التنسيق CSS. + +الآن يجب أن يبدو الملف الخاص بك مثل هذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +حسنا، قم بحفظ الملف وقم بتحديث الموقع! + +![الرقم 14.2](images/color2.png) + +عمل جيد! ربما نود أيضا إعطاء موقعنا متنفس وزيادة الهامش على الجانب الأيسر؟ دعونا نحاول هذا! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +قم بإضافة التعديل أعلاه لملف التنسيق CSS, احفض الملف و أنظر النتيجة! + +![الرقم 14.3](images/margin2.png) + +ربما يمكننا تخصيص الخط في عنوان الصفحة لدينا؟ ألصق هذا `< header >` في ملف `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +كما من قبل، تحقق من الأمر والمكان قبل الارتباط بـ `blog/static/css/blog.css`. هذا السطر سيطلب خط يسمى *Lobster* من "خطوط جوجل " (https://www.google.com/fonts). + +أعثر على `h1` إعلان كتلة (التعليمات البرمجية بين الأقواس `{` `}`) في ملف CSS `blog/static/css/blog.css`. الآن قم بإضافة السطر `font-family: 'Lobster';` بين أقواس، وحدث الصفحة: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![الرقم 14.3](images/font.png) + +عظيم! + +كما ذكر أعلاه، CSS لديها مفهوم طبقات. هذه تسمح لك بتسمية جزء من التعليمات البرمجية ل HTML وتطبيق الأنماط فقط لهذا الجزء، دون التأثير على الأجزاء الأخرى. هذا يمكن ان يكون مفيد جدا! ربما يكون لديك اثنين من divs اللذان يقومان بشيء مختلف (مثل الهيدر او الموضوع الخاص بك). الكلآس يمكن اي يساعدك في جعلها تبدو مختلفة. + +امضي قدماً وقم بتسمية بعض أجزاء من كود HTML. استبدل `header` الذي يحتوي على رأس الصفحة الخاص بك بما يلي: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +الان أضف Class `post` إلى `div` الذي يحتوي مقال مدونة. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +سنقوم الآن بإضافة كتل إعلان لمحددات مختلفة. المحددات التي تبدأ ب `.` تتعلق بالفصول. هناك العديد من الدروس والشروحات التي تتكلم عن CSS في الأنترنت والتي يمكنها مساعدتك على فهم الأكواد التالية. الآن، فقط قم بنسخ ولصق في ملف `blog/static/css/blog.css` خاصتك: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +تم قم بإحاطة تعليمات HTML التي تظهر المقالات: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +في `blog/templates/blog/post_list.html` بهذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +إحفظ الملفات الأن، وقم بتحديث موقع الويب الخاص بك. + +![الرقم 14.4](images/final.png) + +وووهووو! يبدو رائعا أليس كذالك؟ انظر إلى التعليمات البرمجية التي ألصقناها للتو للعثور على الأماكن التي أضفنا فيها كلاسات في HTML واستخدمناها في CSS. أين يمكن عمل تعديل ان اردت للوقت ان يكون turquoise؟ + +لا تخافوا من العبث مع هذه CSS قليلا ومحاولة تغيير بعض الأشياء. اللعب ب CSS يمكن أن يساعدك على فهم ما تقوم به الأشياء المختلفة. إذا كسرت شيء لا تقلق يمكنك اصلاحه دائما! + +نوصي بشدة بالدورات التدريبية المجانية أونلاين "Basic HTML & HTML5" و "Basic CSS" في [freeCodeCamp](https://learn.freecodecamp.org/). يمكن أن تساعدك على تعلم كل شيء عن جعل مواقعك أجمل باستخدام HTML و CSS. + +جاهز للفصل التالي؟! :) \ No newline at end of file diff --git a/ar-SA/deploy/README.md b/ar-SA/deploy/README.md new file mode 100644 index 00000000000..7bf14a2c8a5 --- /dev/null +++ b/ar-SA/deploy/README.md @@ -0,0 +1,246 @@ +# تدشين! + +> **ملاحظه** الفصل التالي قد يكون في بعض الأحيان صعبا. استمر و اعزم على الانتهاء منه؛ التدشين جزء هام من عملية تطوير موقع على شبكة الإنترنت. ويوضع هذا الفصل في منتصف البرنامج التعليمي حتى يمكن لمدربك أن يساعدك في العمليات الأصعب قليلاً لنشر موقع الويب الخاص بك على الإنترنت. وهذا يعني أنه لا يزال يمكنك الانتهاء من البرنامج التعليمي الخاص بك بمفردك إذا نفذ الوقت منك. + +حتى الأن موقعك كان متاحا فقط على حاسوبك. الأن سوف تتعلم كيف تنشره! النشر هو عملية اتاحة التطبيق الخاص بك على شبكة الإنترنت حيث يمكن للناس الذهاب إلى التطبيق الخاص بك و مشاهدته. :) + +كما تعلمت، موقع على شبكة الإنترنت يجب أن يتواجد في خادم. هناك الكثير من مقدمي الخدمة متاحين على شبكة الإنترنت، ونحن سنستخدم [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere متوفر مجانا للتطبيقات الصغيرة التي لا تحتوي على عدد كبير من الزائرين فالآن بالتأكيد ستكون كافية بالنسبة لك. + +الخدمات الخارجية الأخرى ستقوم باستخدام [GitHub](https://www.github.com)، وهي خدمة استضافة التعليمات البرمجية. هناك آخرون ، ولكن تقريبا جميع المبرمجين لديهم حساب GitHub في هذه الأيام، والآن أنت سوف يمكنك أيضا الحصول على حساب! + +سوف تكون هذه الأماكن الثلاثة هامة بالنسبة لك. الكمبيوتر الخاص بك سوف يكون المكان حيث يمكنك القيام بالتطوير والإختبار. عندما تكون راضيا عن التغييرات، ستقوم بوضع نسخة من التعليمات البرمجية على GitHub. موقعك سيكون على بايثون في كل مكان ، وستقوم بتحديثه عبر استقدام نسخة جديدة من GitHub. + +# جيت (Git) + +> **ملاحظة** إذا كنت قمت بإجراء خطوات التثبيت سابقا، لا تحتاج للقيام بذلك مرة أخرى -يمكنك التخطي إلى الجزء التالي والبدء في إنشاء مستودع Git الخاص بك. + +{% include "/deploy/install_git.md" %} + +## ابتداء مستودعك في Git + +Git يتعقب التغييرات التي تحدث لمجموعة معينة من الملفات في ما يسمى بمستودع الكود (أو "الريبو" للاختصار). لنبدأ انشاء مستودع (ريبو) لمشروعنا. افتح وحدة التحكم الخاص بك ، وشغل هذه الأوامر في دليل `djangogirls`: + +> **ملاحظة** تحقق من دليل العمل الحالي الخاص بك مع `pwd` (Mac OS X/لينكس) أو `cd` (في Windows) قبل تهيئة المستودع. يجب أن تكون في المجلد `djangogirls`. + +{% filename %}command-line{% endfilename %} + + $ 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` في الدليل الرئيسي. افتح المحرر الخاص بك وقم بإنشاء ملف جديد مع محتويات التالية: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +واحفظه ك `.gitignore` في مجلد "djangogirls". + +> **ملاحظة** النقطه في بداية اسم الملف مهمه! إذا كنت تواجه أي صعوبة في انشائه (على سبيل المثال ،أجهزة ماكينتوش لا تمكنك من إنشاء الملفات التي تبدأ بنقطة عن طريق الباحث)، إذا قم باستخدام ميزة "حفظ باسم" في المحرر الخاص بك. تأكد من عدم إضافة `.txt`، `py` أو أي امتداد اخر إلى اسم الملف -- سوف يتعرف عليها Git اذا كان الاسم فقط `.gitignore`. يتعامل لينكس وماك مع الملفات التي تبدأ بـ `.` (مثل `.gitignore`) كملفات مخفية و `ls` لن تظهر هذه الملفات. بدلاً من ذلك، استخدم `ls -a` لمشاهدة الملف `.gitignore`. +> +> **ملاحظة** أحد الملفات التي قمت بتحديدها في ملف `.gitignore` هي `db.sqlite3`. هذا الملف هو قاعدة البيانات المحلية الخاصة بك، حيث يتم تخزين جميع المستخدمين والوظائف الخاصة بك. سوف نتابع الممارسات الموحدة في برمجة الويب، بمعنى أنه سوف نستخدم قواعد بيانات منفصلة لموقع الاختبار المحلي الخاص بك وموقع الويب الخاص بك مباشرة في PythonAnywhere. قاعدة بيانات PythonAnywhere يمكن أن تكون SQLite، مثل الة التطوير خاصتك، ولكن عادة ما تستخدم واحدة تدعى MySQL والتي يمكنها التعامل مع عدد زوار أكبر بكثير من SQLite. وفي كلتا الحالتين، بتجاهل قاعدة بيانات SQLite لنسخة GitHub، يعني أن جميع المشاركات التي قمت بإنشائها حتى الآن ستكون متاحة محلياً فقط، وسيكون عليك إنشاء مشاركات جديدة عند الإنتاج. ينبغي أن تفكر في قاعدة البيانات المحلية الخاصة بك كملعب جيد حيث يمكنك اختبار أشياء مختلفة وولا تخف من فكرة انك ستحدف مشاركاتك الحقيقية من المدونة. + +انها فكرة جيدة استخدام الأمر `git status` قبل `git add` أو كلما وجدت نفسك غير متأكد من ما تغير. وهذا سيساعد على منع أي مفاجآت من الحدوث، مثل إضافة ملفات خاطئة. الأمر `git status` يرجع المعلومات عن اي ملف لم يتم اتباعه تعديله او تنظيمه, حالة الفرع، وأكثر من ذلك بكثير. يجب أن يكون المخرج مشابه لما يلي: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +وأخيرا نحفظ التغييرات التي قمنا بها, اذهب الى لوحة التحكم الخاصة بك وأدخل هذه الأوامر: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ 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](https://www.github.com) وسجل حساب مستخدم جديد مجاني. (لو فعلت هذا مسبقاً في التحضير للورشة، هذا شيء عظيم!) تأكد من حفظ كلمة السر (أضفها إلى مدير كلمات السر الخاص بك اذا كنت تستخدم احدهم). + +بعدها أنشئ مستودع جديد. واعطه اسم "my-first-blog". اترك خانة "initialize with a README" دون اختيارها واترك الخيار.gitignore فارغ (لقد فعلنا ذلك يدوياً) وأترك الترخيص على أنه لا شيء. + +![](images/new_github_repo.png) + +> ** * * ملاحظة * * اسم 'my-first-blog' مهم – يمكن أن تختار شيئا آخر، لكن هذا سيأخد الكثير من الوقت في الإرشادات الموجودة أدناه، وسيكون عليك استبداله كل مرة. ربما من الأسهل الإبقاء على اسم 'my-first-blog'.

+> +> في الشاشة التالية، سوف يظهر لك URL استنساخ الريبو الخاص بك، الذي سيتم استخدامه في بعض الأوامر التالية: +> +> ![](images/github_get_repo_url_screenshot.png) +> +> الآن نحن بحاجة إلى ربط مستودع Git على جهاز الكمبيوتر الخاص بك مع المستودع الذي أنشأته على GitHub. +> +> اكتب الأمر التالي في وحدة التحكم الخاصة بك (استبدل `` مع اسم المستخدم الذي قمت بإدخاله عند إنشاء حساب GitHub الخاص بك، ولكن دون أقواس -- هذا الURL يجب أن يشابه الURL المنسوخ الذي رأيته قبل قليل): +> +> {% filename %}command-line{% endfilename %} +> +> $ git remote add origin https://github.com//my-first-blog.git +> $ git push -u origin master +> +> +> عند الرفع إلى GitHub، سيطلب منك GitHub اسم المستخدم وكلمة المرور (أما في نافذة سطر الأوامر أو في نافذة منبثقة)، وبعد إدخال بيانات الاعتماد يجب أن ترى شيئا مثل هذا: +> +> {% filename %}command-line{% endfilename %} +> +> 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/ola/my-first-blog.git +> +> * [new branch] master -> master +> Branch master set up to track remote branch master from origin. +> +> +> +> +> برنامجك الان في GitHub. اذهب وتحقق من ذلك! ستجد في النهاية – \[Django\] (https://github. com/django/django) وفي \[Django Girls Tutorial\] (https://github. com/DjangoGirls/tutorial)، والعديد من مشاريع البرمجيات الكبيرة مفتوحة المصدر تستضيف برامجها الخاصة في GitHub. :) +> +> # اعداد مدونتنا على PythonAnywhere +> +> ## انشئ حساب على PythonAnywhere +> +> > * * ملاحظة * * قد تكون انشأت حساب ب PythonAnywhere في وقت سابق أثناء خطوات التثبيت – إذا كان الأمر كذلك، لا حاجة للقيام بذلك مرة أخرى. +> +> {% include "/deploy/signup_pythonanywhere.md" %} +> +> ## اعداد موقع على PythonAnywhere +> +> عد الى لوحة التحكم بالنقر على شعار الموقع, وحدد خيار بدئ الطرفية (bash-console) هي نسخة الموقع من الطرفية تماما كتلك اللتي لديك بجهازك. +> +> ![جزء ""وحدة التحكم الجديدة" على موقع PythonAnywhere، مع زر "bash"](images/pythonanywhere_bash_console.png) +> +> > **ملاحظة** PythonAnywhere يعتمد ومبني على اللينكس. لذا ان كنت على ويندوز فالطرفية ستظهر مختلفة قليلا. +> +> نشر تطبيق ويب على PythonAnywhere يتضمن سحب التطبيق من GitHub ومن ثم اعداد PythonAnywhere للتعرف عليه وبدء العمل به كتطبيق ويب. هناك طرق يدوية للقيام بذلك, لكن PythonAnywhere يوفر أدوات تقوم بالمهمة عنك. أولا لنثبت لنثبته: +> +> {% filename %}PythonAnywhere command-line{% endfilename %} +> +> $ pip3.8 install --user pythonanywhere +> +> +> يجب أنت ترى بعض الملاحظات ك`Collecting pythonanywhere` و تنتهي بالعبارة `Successfully installed (...) pythonanywhere- (...)`. +> +> الان نستخدم الادات المساعدة, لإعداد التطبيق مباشرة من GitHub و بشكل ألي. اكتب الأمر التالي في وحدة التحكم على PythonAnywhere(لا تنسى أن استخدام اسم المستخدم الخاص بك في GitHub بدلاً من ``، حتى يتشابه الURL بالURL المنسوخ من Github): +> +> {% filename %}PythonAnywhere command-line{% endfilename %} +> +> $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git +> +> +> بينما تشاهد ذلك يعمل، سوف يمكنك رؤية ماذا يفعل: +> +> - تحميل الكود خاصتك من Github +> - إنشاء virtualenv على PythonAnywhere، تماما مثل الذي على جاهز الكمبيوتر خاصتك +> - تحديث ملف الإعدادات مع بعض إعدادات النشر +> - إعداد قاعدة بيانات على PythonAnywhere باستخدام الأمر `manage.py migrate` +> - إعداد الملفات الثابتة (سوف نتعلم عن هذه في وقت لاحق) +> - وتهيئة PythonAnywhere لخدمة التطبيق الويب الخاص بك عبر API، +> +> في PythonAnywhere جميع تلك الخطوات أتوماتيكية، بل أنهم نفس الخطوات التي عليك أن تذهب من خلالها مع أي موفر خدمة آخر. +> +> الشيء الرئيسي الذي يجب ملاحظته الآن هو أن قاعدة البيانات الخاصة بك في PythonAnywhere في الواقع منفصلة تماما من قاعدة البيانات على جهاز الكمبيوتر الخاص بك، حتى تتمكن من أن يكون لها وظائف وحسابات المسؤول(admin) مختلفين. نتيجة لذلك، تماما كما فعلت على جهاز الكمبيوتر خاصتك، علينا بدأ حساب المسؤول(admin) ب `createsuperuser`. قام PythonAnywhere بتفعيل Virtualenv خاصتك أتوماتيكيا، لذلك كل ما تحتاج لفعله هو تشغيل: +> +> {% filename %}PythonAnywhere command-line{% endfilename %} +> +> (ola.pythonanywhere.com) $ python manage.py createsuperuser +> +> +> اكتب التفاصيل للمستخدم المسؤول(admin) الخاص بك. أفضل الطرق لاستخدام نفس الذي تستخدمه على الكمبيوتر الخاص بك لتجنب أي التباس، إلا إذا كنت تريد أن تجعل كلمة المرور على PythonAnywhere أكثر أمنا. +> +> الان، اذا أردت، يمكنك النظر إلى الكود خاصتك على PythonAnywhere باستخدام `ls`: +> +> {% filename %}PythonAnywhere command-line{% endfilename %} +> +> ola.pythonanywhere.com) $ ls) +> blog db.sqlite3 manage.py mysite requirements.txt static +> ola.pythonanywhere.com) $ ls /blog) +> __init__.py __pycache__ admin.py apps.py migrations models.pytests.py static +> templates views.py +> +> +> يمكنك أيضا الذهاب إلى صفحة "ملف" وتصفح حولها باستخدام متصفح الملفات المبني في PythonAnywhere. (من صفحة وحدة التحكم، يمكنك الحصول على صفحات أخرى في PythonAnywhere من زر القائمة في الزاوية العلوية اليمنى. وعند تواجدك في إحدى الصفحات، هناك روابط لبعضها الآخر بالقرب من الأعلى.) +> +> ## أنت على الهواء الأن! +> +> يجب أن يكون موقعك الآن مباشرًا على الإنترنت العام! انقر من خلال صفحة PythonAnywhere "Web" للحصول على رابط له. يمكنك مشاركة هذا مع أي شخص تريده. :) +> +> > **ملاحظة** هذا برنامج تعليمي للمبتدئين، وفي نشر هذا الموقع لقد اتخذنا بعض التجاوزات التي لم تكن مثالية من وجهة نظر أمنية. إذا قررت البناء على هذا المشروع، أو البدء في مشروع جديد، يجب عليك مراجعة [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) للحصول على بعض النصائح حول رفع مستوى أمان موقعك. +> +> ## نصائح لتصحيح الأخطاء +> +> إذا كنت ترى خطأ أثناء تشغيل البرنامج النصي `pa_autoconfigure_django.py`، فيما يلي بعض الأسباب الشائعة: +> +> - نسيان إنشاء رمز API الخاص بPythonAnywhere. +> - إرتكاب خطأ في عنوان Github URL الخاص بك +> - إذا كنت ترى خطأ يقول *"تعذر العثور على settings.py الخاص بك"*، على الأرجح لأنك لم تتمكن من إضافة كافة الملفات الخاصة بك إلى Git، و/أو لم ترفعهم إلى GitHub بنجاح. ألقي نظرة أخرى على قسم Git أعلاه +> - إذا كنت مسجل سابقاً في PythonAnywhere وحصلت لك مشكلة في collectstatic، فغالباً لديك في حسابك نسخة أقدم من SQLite (مثل 3.8.2). في هذه الحالة، سجل في حساب جديد وجرب الأوامر البرمجية الموجودة في قسم PythonAnywhere في الأعلى. +> +> إذا كنت ترى خطأ عند محاولة زيارة موقع الويب الخاص بك، المكان الأول للبحث عن بعض معلومات التصحيح هو **سجل الأخطاء** الخاص بك. ستجد رابط لهذا في PythonAnywhere [صفحة "الويب"](https://www.pythonanywhere.com/web_app_setup/). إذا كان هناك أية رسائل أخطاء هناك؛ أحدثها يوجد في الأسفل. +> +> وهناك أيضا بعض [نصائح عامة لتصحيح الأخطاء في موقع المساعدة لPythonAnywhere](http://help.pythonanywhere.com/pages/DebuggingImportError). +> +> وتذكر أن المدرب هنا للمساعدة! +> +> # تحقق من موقع الويب الخاص بك! +> +> الصفحة الرئيسية لموقعك يجب ان تقول "لقد نجح!" تماما كما تقول على حاسوبك الخاص. حاول إضافة `/admin/` إلى نهاية عنوان URL، وسوف يتم نقلك إلى موقع المشرف. قم بتسجيل الدخول باستخدام اسم المستخدم وكلمة المرور، وسترى أنه يمكنك إضافة وظائف جديدة على الخادم -- تذكر، مشاركاتك من قاعدة البيانات المحلية الخاصة بك لم يتم إرسالها إلى مدونتك المباشرة. +> +> وبمجرد الانتهاء من إنشاء عدد قليل من المشاركات، يمكنك العودة إلى الإعداد المحلي الخاص بك (ليس PythonAnywhere). من هنا يجب أن تعمل على الإعدادات المحلية خاصتك لإجراء التغييرات. هذا سير عمل مشترك في تطيور المواقع -- قم بالتغييرات محلياً، ارفع تلك التغييرات إلى GitHub، وارسل هذه التغييرات إلى خادم الويب المباشر خاصتك. هذا يسمح لك بالعمل والتجربة دون تخريب موقع الويب الخاص بك. رائع! اليس كذالك؟ +> +> إعطي نفسك تربيت *كبير* على الظهر! عمليات نشر الخوادم واحدة من أصعب أجزاء تطوير المواقع، وكثيراً ما يأخذ الناس عدة أيام قبل أن تتمكن من فعلها. ولكنك قد نشرت موقعك الخاص على شبكة الانترنت! \ No newline at end of file diff --git a/ar-SA/deploy/install_git.md b/ar-SA/deploy/install_git.md new file mode 100644 index 00000000000..5f86ecba4b1 --- /dev/null +++ b/ar-SA/deploy/install_git.md @@ -0,0 +1,52 @@ +Git عباره عن "نظام تحكم في الإصدار" مستخدم من قبل الكثير من المبرمجين. هذا النظام يمكنه تعقب التغييرات في الملفات مع مرور الوقت حتى أنه يمكنك استرجاع إصدارات محددة في وقت لاحق. قليلاً مثل ميزة "تعقب التغييرات" في برامج معالج النصوص (على سبيل المثال، Microsoft Word أو Writer LibreOffice)، ولكن أقوى بكثير. + +## تثبيت Git + + + +يمكنك تحميل Git من [ git-scm.com](https://git-scm.com/). يمكنك الضغط على "التالي" في جميع الخطوات باستثناء خطوتين: في الخطوة التي يطلب منك اختيار محررك، عليك اختيار Nano, وفي الخطوة بعنوان "ضبط بيئة المسار (PATH) الخاص بك"، اختر "استخدام Git وأدوات يونيكس المرتبطة بها من سطر الأوامر في ويندوز" (الخيار الأسفل). بخلاف ذلك، الإعدادات الافتراضية كافيه. راجع نهايات السطور في نمط ويندوز ، و ارتكاب نمط يونكس. + +لا تنس إعادة تشغيل موجه الأوامر أو powershell بعد انتهاء عملية التثبيت بنجاح. + + + +تحميل Git من [.git-scm.com](https://git-scm.com/) واتبع التعليمات. + +> **ملاحظة** إذا كنت تستخدم نضظم ماك بهذه الإصدارات OS X 10.6, 10.7, or 10.8, يجب عليك تنصيب نسخة git من هذا الرابط [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/ar-SA/deploy/signup_pythonanywhere.md b/ar-SA/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..616262b0905 --- /dev/null +++ b/ar-SA/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere هي خدمة لتشغيل أكواد بايثون على خوادم سحابية. سوف نستخدمها لنشر موقعك، مباشرة وعلى الانترنت. + +سوف نقوم بنشر المدونة التي سنبنيها على PythonAnywhere. أنشئ حساب "مبتدأ" على PythonAnywhere (الحساب المجاني كافي، لا تحتاج بطاقة ائتمان). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![صفحة إنشاء الحساب في PythonAnywhere تظهر زر لإنشاء حساب مجاني للمبتدئين](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **ملاحظة** عندما تقوم باختيار اسم المستخدم (username) هنا، تذكر ان رابط مدونتك سوف يأخذ الشكل `yourusername.pythonanywhere.com`، لذلك قم باختيار اسم مستعارا لك او اسم يدل علآ محتوى المدونة خاصتك. أيضا، تأكد من تذكر كلمة المرور الخاصة بك (اضفها الى مدير كلمات السر خاصتك، إذا كنت تستخدم أحدهم). + +## إنشاء قطعة واجهة التطبيق البرمجية (API) من PythonAnywhere + +هذا شيء تحتاج لفعله مرة واحدة فقط. عندما تنتهي من إنشاء حساب PythonAnywhere، سوف يتم أخذك إلى اللوحة الرئيسية. ابحث عن رابط في أعلى الصفحة، على يمين صفحة الحساب: + +![رابط الحساب يوجد في أعلى يمين الصفحة](../deploy/images/pythonanywhere_account.png) + +ثم اختر خلية تسمى قطعة واجهة التطبيق البرمجية (API token)، واضغط على الزر الذي يقول: "أنشىء قطعة واجهة تطبيق برمجية جديدة" (Create new API token). + +![خلية قطعة واجهة التطبيق البرمجية (API token) في صفحة الحساب](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/ar-SA/django/README.md b/ar-SA/django/README.md new file mode 100644 index 00000000000..c3abb2773a0 --- /dev/null +++ b/ar-SA/django/README.md @@ -0,0 +1,27 @@ +# ما هو جانغو؟ + +جانغو (/ˈdʒæŋɡoʊ/*جانغ-جوه*) إطار تطبيق ويب حر ومفتوح المصدر مكتوب بلغة بايثون. أطار العمل مكون من مجموعه من المكونات التى سوف تساعدك على تطوير المواقع بطريقة اسهل واسرع. + +عندما تقوم ببناء موقع على شبكة الإنترنت، تحتاج دائماً مجموعة مماثلة من المكونات: طريقة للتعامل مع مصادقة المستخدم (التسجيل، الدخول، والخروج)، وصفحة إدارية لموقع الويب الخاص بك، والاستمارات، وطريقة لتحميل الملفات، إلخ. + +لحسن الحظ لاحظ أشخاص آخرين منذ وقت طويل أن مطوري الويب تواجههم مشاكل مماثلة عند إنشاء موقع جديد، فتعاونوا في إنشاء أطارات عمل (جانغو واحد منهم) التي تعطيك مكونات جاهزة يمكنك استخدامها. + +اطارات العمل موجودة لتنقدكم من إعادة اختراع ما تم اختراعه من قبل، وتساعد في تخفيف بعض النفقات العامة عندما تقوم ببناء موقع جديد. + +## لماذا تحتاج إلى إطار عمل؟ + +لفهم ما هو جانغو في الواقع ، علينا أن نلقي نظرة فاحصة على الملقمات. أول شيء أن الملقم يحتاج إلى معرفة أن كنت تريد منه ان يعطيك صفحة انترنت. + +تخيل علبة بريد (ميناء) التي يتم ضبطها للرسائل الواردة (الطلبات). وهذا يتم عن طريق خادم ويب. خادم الويب يقوم بقراءة الرسالة وثم يرسل استجابة مع صفحة ويب. ولكن عندما تريد أن ترسل شيئا، فأنت بحاجة إلى بعض المحتوى. وجانغو هو الشيء الذي يساعدك في إنشاء المحتوى. + +## ماذا يحدث عندما يطلب شخص ما موقع انترنت من خادمك؟ + +عندما يصل طلب إلى الخادم ، يتم تمريره لدجانغو ، والذي سيحاول ما الذي تم طلبه. إنه يأخذ عنوان صفحة ويب أولا ويحاول معرفة ما يجب القيام به. يتم هذا الجزء من قبل دجانغو ** urlresolver** (لاحظ أن عنوان موقع ويب يسمى URL - محدد مواقع الموارد - لذلك الاسم * urlresolver * منطقي). أنه ليس ذكية جدا - فإنه يأخذ قائمة من الأنماط ويحاول مطابقة عنوان URL. جانغو يتحقق من الأنماط من أعلى إلى أسفل، وإذا تم مطابقة شيء، يقوم جانغو بتمرير الطلب إلى الدالة المرتبطة بها (والتي تسمى *view*). + +تخيل ناقل البريد مع رسالة. تتمشى في الشارع وتفحص جميع ارقام البيوت مع الرقم الموجود في الرسالة. اذا كان مطابقا ، تضع الرسالة هناك. هذه هي الطريقة التي يعمل urlresolver بها! + +في الدالة *view*، تتم جميع الأمور المثيرة للاهتمام: يمكننا أن ننظر إلى قاعدة بيانات للبحث عن بعض المعلومات. ربما طلب المستخدم بتغيير شيء ما في البيانات؟ مثلما تقول الرسالة: "يرجى تغيير وصف وظيفتي". يمكن ل * view* التحقق مما إذا كان مسموحا لك القيام بذلك، ثم تحديث الوصف الوظيفي لك وإرسال رسالة مرة أخرى: "تم!" ثم * view* يولد استجابة و جانغو يمكن أن يرسلها إلى متصفح الويب الخاص بالمستخدم. + +بالطبع الوصف اعلاه مبسط كثيرا ، لكنك لست في حاجة لمعرفة كل المعلومات التقنية حاليا، الحصول على فكرة عامة كافي. + +لذلك بدلا من الغوص كثيرا في التفاصيل، نحن سوف نبدأ ببساطة بصناعة شيء باستخدام جانغو وسنتعلم كل الأجزاء المهمة على طول الطريق! \ No newline at end of file diff --git a/ar-SA/django_admin/README.md b/ar-SA/django_admin/README.md new file mode 100644 index 00000000000..8acd42ffa88 --- /dev/null +++ b/ar-SA/django_admin/README.md @@ -0,0 +1,57 @@ +# مشرف Django + +لإضافة وتعديل وحذف المشاركات التي قمنا بإضافتها، سوف نستخدم دجانغو المشرف. + +دعنا نفتح ملف `blog/admin.py` في محرر الأكواد ونبدل محتوياته بهذا: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +كما ترون، نقوم باستيراد (تضمين) نموذج المشاركة المحدد في الفصل السابق. لجعل نموذجنا مرئيا على صفحة المشرف، نحن بحاجة إلى تسجيل النموذج مع `admin.site.register(Post)`. + +حسنا حان الوقت للنظر في نموذجنا. تذكر أن تقوم بتشغيل `python manage.py runserver` في وحدة التحكم لتشغيل خادم ويب. اذهب إلى المتصفح واكتب http://127.0.0.1:8000/admin/. ستظهر لك صفحة تسجيل دخول مثل هذه: + +![صفحة تسجيل الدّخول](images/login_page2.png) + +لتسجيل الدخول، تحتاج إلى إنشاء مستخدم *superuser*-حساب مستخدم له السيطرة على كل شيء في الموقع. ارجع إلى سطر الأوامر، واكتب `python manage.py createsuperuser`,، ثم اضغط على إنتر. + +> تذكر، لكتابة الأوامر الجديدة أثناء تشغيل خادم الويب، إفتح نافذة جديدة وفعل البيئة الإفتراضية الخاصة بك. علينا إعادة النظر في كيفية كتابة أوامر جديدة خلال فصل **أول مشروع جانغو لك!** ، في المقطع **بدء تشغيل خادم ويب**. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +عند الطلب، اكتب اسم المستخدم (أحرف صغيرة، لا مسافات)، وعنوان البريد الإلكتروني، وكلمة المرور. **لا تقلق لأنك لا تستطيع رؤية كلمة السر التي تكتبها- هذا ما يجب ان يحصل. ** اكتبها واضغط `ادخل` لتكمل. يجب أن يظهر الناتج على هذا النحو (حيث يجب أن يكون اسم المستخدم والبريد الإلكتروني هو اسم المستخدم الخاص بك): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +ارجع إلى المتصفح. سجل الدخول باستخدام بيانات اعتماد المستخدم الخارق التي اخترتها؛ يجب أن ترى لوحة قيادة دجانغو المشرف. + +![دجانغو المشرف](images/django_admin3.png) + +اذهب إلى Posts وجرب. أضف خمس أو ست مقالات. لا تقلق بشأن المحتوى –- سيكون في جهازك الشخصي فقط – تستطيع نسخ النص الموجود في هذه الصفحة لاختصار الوقت. :) + +تأكد من أن اثنين أو ثلاث مشاركات على الأقل (ليس جميعها) لها تاريخ نشر. سوف يكون هذا مفيد لنا في وقت لاحق. + +![دجانغو المشرف](images/edit_post3.png) + +إذا كنت تريد معرفة المزيد حول مشرف دجانغو من خلال قراءة دليل جانقو: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +ربما تكون هذه لحظة جيدة لشرب كوب من القهوة (أو الشاي) أو لتناول الطعام لإعادة تنشيط نفسك. لقد قمت بإنشاء أول نموذج جانغو خاص بك أنت تستحق الإستراحة قليلا! \ No newline at end of file diff --git a/ar-SA/django_forms/README.md b/ar-SA/django_forms/README.md new file mode 100644 index 00000000000..3b8941efd18 --- /dev/null +++ b/ar-SA/django_forms/README.md @@ -0,0 +1,480 @@ +# نماذج جانغو + +الشيء الأخير الذي نريد القيام به على موقعنا هو خلق وسيلة لطيفة لإضافة وتحرير مشاركات مدونتنا. دجانغو `admin` جميل ، لكن من الصعب تخصيصه وجعله جميلا. مع `forms` سيكون لدينا سلطة مطلقة على واجهتنا – يمكن أن نفعل أي شيء تقريبا يمكن أن نتصور! + +الشيء الجميل حول أشكال جانغو هو أنه يمكننا تخصيص واحد من الصفر أو إنشاء `ModelForm` الذي سيحفظ نتيجة النموذج في الشكل. + +هذا بالضبط ما نريد فعله سننشئ شكل لنمودج `Post`. + +مثل كل جزء مهم من دجانغو، فإن النماذج لها ملف خاص بها `forms.py`. + +نحن بحاجة إلى إنشاء ملف بهذا الاسم في دليل `blog`. + + blog + └── forms.py + + +حسنًا، دعونا نفتحه في محرر التعليمات البرمجية (أي في البرنامج الذي تكتب فيه الأكواد) ونكتب التعليمات البرمجية التالية: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +نحتاج أولا الى جلب و احضار نماذج جانغو (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`,، كما كنت تظن ربما، هو اسم النموذج. نحن بحاجة إلى أن نقول لدجانغو ان هذا النموذج هو `ModelForm`(لذلك جانغو ستقوم ببعض السحر `forms.ModelForm` هو المسؤول عن ذلك. + +تاليا ، لدينا `class Meta` والذي يقول لدجانغو اي نمودج يجب استخدامه لإنشاء الشكل (`model = Post`). + +وأخيراً، يمكننا أن نقول ياي حقول يجب ان تنتهي في شكلنا. في هذا السيناريو نريد فقط `title` و `text` عرضه – – `author` ينبغي أن يكون الشخص الذي قام بتسجيل هو (أنت!) ويجب تعيين `created_date` تلقائياً عندما نقوم بإنشاء مشاركة (أي في التعليمات البرمجية)، اليس كذالك؟ + +وهذا كل شيء! كل ما يتعين علينا فعله الآن هو استخدام الشكل في *view* وعرضه في نموذج. + +لذلك مرة أخرى سنقوم بإنشاء رابط إلى صفحة، UR، والعرض والقالب. + +## رابط لصفحة مع الشكل + +قبل أن نضيف الرابط، نحتاج إلى بعض الأيقونات لاستخدامها كأزرار للرابط. لهذا البرنامج التعليمي، قم بتنزيل [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) وحفظه في المجلد `blog/templates/blog/icons/` + +> ملاحظة: لتنزيل صورة SVG، قم بفتح قائمة السياق على الرابط (عادة بالنقر على اليمين عليه) واختر "حفظ الرابط ك". في مربع الحوار الذي يسألك أين تحفظ الملف، انتقل إلى دليل `djangogirl` لمشروع جانغو الخاص بك. وفي ذلك إلى الدليل الفرعي `blog/templates/blog/icons`، وحفظ الملف هناك. + +حان الوقت لفتح `blog/templates/blog/base.html` في محرر التعليمات البرمجية. الآن يمكننا استخدام ملف الأيقونة هذا داخل قالب القاعدة كما يلي. في عنصر `div` داخل قسم `header` ، سنضيف رابط قبل عنصر `h1`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +لاحظ أننا نريد تسمية العرض الجديد `post_new`. الـ SVG icon [](https://icons.getbootstrap.com/icons/file-earmark-plus/) مقدم من [Bootstrap Icons](https://icons.getbootstrap.com/) وسوف يعرض أيقونة صفحة مع علامة زائد. نحن نستخدم موجه قالب جانغو يسمى `include`. سيؤدي هذا إلى حقن محتوى الملف في قالب جانغو. متصفح الويب يعرف كيفية التعامل مع هذا النوع من المحتوى دون أي معالجة أخرى. + +> يمكنك تنزيل جميع أيقونات Bootstrap [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). فك ضغط الملف وانسخ جميع ملفات صور SVG في مجلد جديد داخل `blog/templates/blog/` يسمى `icons`. بهذه الطريقة يمكنك الوصول إلى أيقونة مثل `pencil-fill.svg` باستخدام مسار الملف `blog/templates/blog/icons/pencil-fill.svg` + +بعد تعديل السطر ، يجب أن يبدو ملف HTML الخاص بك مثل هذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + + +``` + +بعد حفظ و تحديث الصفحة : http://127.0.0.1:8000 سوف ترى خطأ مألوف! `NoReverseMatch` هل هذا ما حدث معك/معكي؟ جيد !! + +## عنوان الموقع URL + +نقوم بفتح `blog/urls.py` في محرر التعليمات البرمجية وإضافة سطر: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +وسوف تبدو التعليمات البرمجية النهائية هكذا: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +بعد تحديث الموقع، نرى `AttributeError`، حيث أننا ليس لدينا `post_new` طريقة عرض منفذة. دعونا نضيفها الآن. + +## عرض post_new + +حان الوقت لفتح `blog/views. y` الملف في محرر التعليمات البرمجية وإضافة الأسطر التالية مع بقية صفوف `from`: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +عندها *view* الخاصة بنا: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +لإنشاء نموذج `Post` جديد، نحن بحاجة إلى استدعاء `PostForm()` وتمريرها إلى القالب. سنعود لهذا *view* لكن الأن دعونا ننشئ شكل نمودج سريعا. + +## القالب + +نحن بحاجة إلى إنشاء ملف `post_edit.html` في الدليل `blog/templates/blog`، وفتحه في محرر التعليمات البرمجية. لجعل النموذج يعمل نحن بحاجة إلى عدة أشياء: + +* علينا عرض الشكل. يمكننا أن نفعل ذلك عبر (على سبيل المثال{% raw %}`{{ form.as_p }}`{% endraw %}. +* يجب تغليف السطر أعلاه مع عنصر نموذج HTML: `...`. +* ونحن بحاجة إلى زر `Save`. ونحن نفعل ذلك مع زر HTML: ``. +* وأخيراً، فقط بعد افتتاح العلامة `
` نحن بحاجة إلى إضافة {% raw %} `{% csrf_token %}`{% endraw %}. هذا أمر مهم جداً، لأنه يجعل النماذج الخاصة بك آمنة! إذا كنت قد نسيت هذا قليلاً، سيشكو جانغو عند محاولة حفظ النموذج: + +![صفحة الـ CSFR المحظورة](images/csrf2.png) + +حسنًا، دعونا نرى كيف يجب أن تبدو HTML في `post_edit.html`: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +حان وقت التحديث! ياي! يتم عرض النموذج الخاص بك! + +![نموذج جديد](images/new_form2.png) + +ولكن انتظر لحظة! عندما تكتب شيئا في حقول `title` و `text` ومحاولة حفظه، ما الذي سيحدث؟ + +لا شيء! نحن مرة أخرى في نفس الصفحة و النص الخاص بنا يذهب… و لم تتم إضافة أي مشاركة جديدة. إذاً ماذا خطأ؟ + +الجواب: لا شيء. نحن بحاجة إلى العمل أكثر قليلاً في *view*. + +## حفظ الشكل + +افتح `blog/views.py` مرة أخرى في محرر التعليمات البرمجية. حاليا كل ما لدينا في العرض `post_new` هو التالي: + +{% filename %}blog/views.py{% endfilename %} + +```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* الخاص بنا لدينا حالتين منفصلتين للتعامل معهما: أولا، عندما نصل إلى الصفحة لأول مرة ونريد نموذج فارغ، وثانيا، عندما نعود إلى *view* مع جميع بيانات النموذج التي كتبناها للتو. لذا نحن بحاجة إلى إضافة شرط (سنستخدم `if` لذلك): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +حان الوقت لملء النقاط `[...]`. إذا كانت الطريقة `` `POST` إذاً نريد بناء `PostForm` مع بيانات من النموذج، أليس كذلك؟ سوف نفعل ذلك على النحو التالي: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +الشيء التالي هو التحقق مما إذا كان النموذج صحيح (تم تعيين جميع الحقول المطلوبة ولم يتم تقديم أية قيم غير صحيحة). ونحن نفعل ذلك عبر `form.is_valid()`. + +نتحقق مما إذا كان النموذج صالح وإذا كان كذلك، يمكننا حفظه! + +{% filename %}blog/views.py{% endfilename %} + +```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` لمشاركتنا التي تم إنشاؤها حديثا في المدونة، أليس كذلك؟ ولتحقيق ذلك، نحتاج إلى استيراد: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +أضفه في بداية الملف. والآن يمكننا أن نقول: "انتقل إلى صفحة `post_detail` للمشاركة التي تم إنشاؤها حديثا": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` هو اسم العرض الذي نريد الذهاب اليه. تذكر أن هذا *view* يتطلب متغير `pk`؟ لتمريرها إلى العرض، نستخدم `pk=post.pk`، حيث `post` هي مشاركة المدونة التي تم إنشاؤها حديثا! + +حسنا، لقد تحدثنا كثيرا، ولكن ربما نريد أن نرى ما يبدو عليه *view* الآن، أليس كذلك؟ + +{% filename %}blog/views.py{% endfilename %} + +```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`! + +ربما لاحظتم أننا نضع تاريخ النشر قبل حفظ المشاركة. وفي وقت لاحق سوف نقدم *publish button* في **Django Girls Tutorial: Extensions**. + +هذا رائع! + +> وبما أننا استخدمنا مؤخرا واجهة المشرف في جانغو، فإن النظام يعتقد حاليا أننا لا نزال مسجلين الدخول. هناك بعض الحالات التي يمكن أن تؤدي بنا إلى تسجيل الخروج (إغلاق المتصفح، إعادة تشغيل DB، إلخ.). إذا وجدت عند إنشاء مشاركة، أنك تحصل على أخطاء تشير إلى عدم وجود مستخدم مسجل الدخول، انتقل إلى صفحة المشرف http://127.0.0.1:8000/admin وسجل الدخول مرة أخرى. وهذا سيحل المشكلة مؤقتاً. هناك إصلاح دائم في انتظاركم في فصل **Homework: add security to your website!** بعد البرنامج التعليمي الرئيسي. + +![خطأ في تسجيل الدخول](images/post_create_error.png) + +## التحقق من صحة النموذج + +الآن، سوف نريكم كيف أن أشكال جانغو رائعة. يجب أن تحتوي مشاركة المدونة على حقول `title` و `text`. في نموذج `Post` لدينا لم نقل أن هذه الحقول (على عكس `published_date` غير مطلوبة. لذلك جانغو، بشكل افتراضي، يتوقع أن يتم تعيينهم. + +حاول حفظ النموذج بدون `title` و `text`. خمن ما سيحدث! + +![التحقق من صحة النموذج](images/form_validation2.png) + +جانغو يحرص على التحقق من صحة جميع الحقول في شكلنا ان كانت صحيحة. أليس هذا رائع؟ + +## تحرير النموذج + +الآن نحن نعرف كيفية إضافة مشاركة جديدة. ولكن ماذا لو أردنا تعديل واحدة موجودة بالفعل؟ هذا مشابه جدا لما قمنا به. لنقم بإنشاء بعض الأمور الهامة بسرعة. (إذا كنت لا تفهم شيئا، يجب أن تسأل المدرب الخاص بك أو تنظر في الفصول السابقة، لأننا غطينا جميع هذه الخطوات مسبقاً.) + +أولا، دعونا نحفظ الرمز الذي يمثل زر التحرير. قم بتنزيل [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) وحفظه في الموقع `blog/templates/blog/icons/`. + +افتح `blog/templates/blog/post_detail.html` في محرر التعليمات البرمجية وأضف التعليمات البرمجية التالية داخل عنصر `article`: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +بحيث يبدو القالب كما يلي: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +افتح `blog/urls.py` في محرر التعليمات البرمجية، وأضف هذا السطر: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +سنقوم بإعادة استخدام القالب `blog/templates/blog/post_edit.html`، لذلك آخر شيء مفقود هو *view*. + +دعونا نفتح `blog/views.py` وإضافة هذا في نهاية الملف: + +{% filename %}blog/views.py{% endfilename %} + +```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` إضافي من `urls`. بعد ذلك، نحصل على نموذج `Post` الذي نريد تعديله مع `get_object_or_404(Post, pk=pk)` وثم عندما نقوم بإنشاء نموذج، فإننا نمرر هذا المنشور كـ `instance`، كلاهما عندما نحفظ النموذج… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…وعندما نكون قد فتحنا للتو نموذج مع هذا المنشور للتحرير: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +حسنا، دعونا نختبر إذا كان يعمل! لننتقل إلى صفحة `post_detail`. يجب أن يكون هناك زر تعديل في الركن العلوي الأيسر: + +![زر التعديل](images/edit_button2.png) + +عند النقر عليه سترى النموذج مع مشاركة مدونتنا: + +![تعديل النموذج](images/edit_form2.png) + +لا تتردد في تغيير العنوان أو النص وحفظ التغييرات! + +تهانينا! أصبح تطبيقك أكثر وأكثر اكتمالاً! + +إذا كنت بحاجة إلى مزيد من المعلومات حول نماذج جانغو، فيجب عليك قراءة الوثائق: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## الحماية + +التمكن من إنشاء مشاركات جديدة بالنقر على رابط رائع! ولكن في الوقت الراهن، أي شخص يقوم بزيارة موقع الويب الخاص بك سوف يكون قادر على انشاء مشاركة جديدة، وهذا شيء ربما لا تريده. دعونا تجعل الزر يظهر لك و ليس لأي شخص آخر. + +افتح `blog/templates/blog/base.html` في محرر التعليمات البرمجية، ابحث عن `div` في داخل `header` وعلامة المرساة التي وضعتها سابقاً. يجب أن تبدو هكذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +سوف نضيف علامة `{% if %}` أخرى إلى هذا، والذي سيجعل الرابط يظهر فقط للمستخدمين الذين تم تسجيل دخولهم كمشرفين. الآن، إنه أنت فقط! قم بتغيير عنصر `` ليبدو هكذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +سيؤدي هذا `{% if %}` إلى إرسال الرابط إلى المتصفح فقط إذا كان المستخدم الذي يطلب الصفحة مسجل الدخول. هذا لا يحمي إنشاء مشاركات جديدة تماماً، ولكنها خطوة أولى جيدة. سنقوم بتغطية المزيد من الأمان في دروس الإضافة. + +تذكر رمز التحرير الذي أضفناه للتو إلى صفحة التفاصيل؟ نحن أيضا نريد إضافة نفس التغيير هناك، لذلك لن يتمكن الأشخاص الآخرون من تحرير المشاركات الموجودة. + +افتح `blog/templates/blog/post_detail.html` في محرر التعليمات البرمجية وابحث عن هذا السطر: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +غيره إلى هذا: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +نظرا لأنك مسجل الدخول، إذا قمت بتحديث الصفحة، فلن ترى شيئا مختلفا. حمل الصفحة في متصفح مختلف أو نافذة متخفية (تسمى "InPrivate" في Windows Edge)، على الرغم من ذلك، وسترى أن الرابط لا يظهر، ولا تعرض الأيقونة أيضا! + +## شيء اخر: وقت النشر! + +دعونا نرى ما إذا كان كل هذا يعمل على PythonAnywhere. حان الوقت لنشر آخر! + +* أولاً، فوّض التعليمات البرمجية الخاصة بك، وادفعها إلى GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* وبعد ذلك، في وحدة [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(تذكر أن تستبدل `` بالمجال الفرعي لـ PythonAnywhere الفعلي، بدون أقواس الزاوية. ) + +* أخيراً، اقفز إلى ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (استخدم زر القائمة في الجزء العلوي الأيمن من وحدة التحكم) واضغط على **Reload**. قم بتحديث مدونة https://subdomain.pythonanywhere.com لرؤية التغييرات. + +هذا ينبغي ان يكون كل شيء! مبروك:) \ No newline at end of file diff --git a/ar-SA/django_installation/README.md b/ar-SA/django_installation/README.md new file mode 100644 index 00000000000..a0039c83b8e --- /dev/null +++ b/ar-SA/django_installation/README.md @@ -0,0 +1,7 @@ +# تثبيت جانغو + +> **ملاحظة** إذا كنت تستخدم كروم بوك، تخطي هذا الفصل وتأكد من اتباع [تعليمات إعداد كروم بوك](../chromebook_setup/README.md). +> +> **ملاحظة** إذا كنت قد عملت بالفعل على [خطوات التثبيت](../installation/README.md) إذاً لقد أنهيت هذا بالفعل - يمكنك الانتقال مباشرة إلى الفصل التالي! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/ar-SA/django_installation/instructions.md b/ar-SA/django_installation/instructions.md new file mode 100644 index 00000000000..a966a271c66 --- /dev/null +++ b/ar-SA/django_installation/instructions.md @@ -0,0 +1,229 @@ +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots). +> +> جزء من هذا القسم يستند [django-marcador tutorial](http://django-marcador.keimlink.de/) المرخص لها بمرخصة بموجب المشاع الإبداعي   إسناد-على غرار 4.0 الترخيص الدولي. البرنامج التعليمي django-marcador حقوق الطبع والنشر من قبل Markus Zapke-Gründemann وآخرون. + +## البيئة الافتراضية + +قبل تنصيب دجانغو ، سوف نقوم بتنصيب اداة جد مهمة وستساعدنا كثيرا،في الحفاظ على بيئة كتابة التعليمات البرمجية الخاصة بك مرتبة على جهاز الكمبيوتر. من الممكن تخطي هذه الخطوة، ولكن نحن يوصي بشدة بها. بدءاً من الإعداد الأفضل والذي سيحميك من الكثير من المتاعب في المستقبل! + +هيا لننشئ **بيئة افتراضية** ، تسمى ايضا ب *virtualenv*. سوف تعزل البيئة الإفتراضية إعدادات بايثون / دجانغو الخاص بك على أساس كل مشروع. وهذا يعني أن أية تغييرات تقوم بإجرائها على موقع واحد لن تؤثر على المواقع الأخرى التي تطورها. أنيق، أليس كذالك؟ + +كل ما عليك القيام به هو العثور على الدليل الذي تريد إنشاء `virtualenv`؛ فيه الدليل الرئيسي الخاص بك، على سبيل المثال. في Windows قد تبدو مثل `C:\Users\Name` (حيث `Name` هو اسم تسجيل الدخول الخاص بك). + +> **ملاحظة:** في Windows، تأكد من أن هذا الدليل لا يحتوي على أحرف هجائية أو خاصة؛ إذا كان اسم المستخدم الخاص بك يحتوي على أحرف هجائية، استخدام دليل مختلف، على سبيل المثال `C:\djangogirls`. + +في هذا البرنامج التعليمي سوف نستخدم دليل جديد `djangogirls` من الدليل الرئيسي الخاص بك: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +سوف نقوم بإنشاء بيئة افتراضية تسمى `myvenv`. سوف تكون القيادة العامة في التنسيق: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +لإنشاء `virtualenv`, جديد، تحتاج إلى فتح موجه الأوامر وتشغيل `python -m venv myvenv`. وسوف تبدو كما يلي: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +حيث `myvenv` هو اسم خاص ب `virtualenv`. يمكنك استخدام أي اسم آخر، لكن حافض على الحروف الصغيرة ولا تستخدم مسافات أو لهجات أو أحرف خاصة. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +يمكننا إنشاء `virtualenv` على لينكس ونظام التشغيلOS X عن طريق تشغيل `python3 -m venv myvenv`: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +حيث `myvenv` هو اسم خاص ب `virtualenv`. يمكنك استخدام أي اسم آخر، لكن حافض على الحروف الصغيرة ولا تستخدم مسافات. كما أنها فكرة جيدة الحفاظ على الاسم قصير – سوف تستخدمه كمرجع كثيرا! + +> **ملاحظة:** في بعض الإصدارات من ديبيان/أوبونتو قد تتلقى الخطأ التالي: +> +> {% filename %}command-line{% endfilename %} +> +> لم يتم إنشاء البيئة الإفتراضية بنجاح لأن ensurepip غير متوفر. على أنظمة ديبيان/أوبونتو، تحتاج إلى تثبيت حزمة python3-venv باستخدام الأمر التالي. +> apt-get install python3-venv +> غالبا ستحتاج إستعمال sudo لتنفيد الأمر. بعد تثبيت حزمة python3-venv، قم بإعادة إنشاء البيئة الإفتراضية الخاصة بك. +> +> +> في هذه الحالة اتبع التعليمات تحت وثبت حزمة `python3-venv` {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **ملاحظة:** في بعض إصدارات ديبيان/أوبونتو اعداد البيئة الإفتراضية بهذه الطريقة قد يعطي هذا الخطأ: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> للالتفاف على هذا، استخدم الأمر `virtualenv` بدلاً من ذلك. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **ملاحظة:** إذا حصلت على خطأ مثل +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> قم بتنفيد الأمر: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## العمل مع virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +بدء تشغيل البيئة الإفتراضية الخاصة بك عن طريق تشغيل: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. وفي هذه الحالة، قم بفتح Windows PowerShell آخر باستخدام الخيار "تشغيل كمسؤول". ثم حاول كتابة الأمر التالي قبل تشغيل البيئة الإفتراضية الخاصة بك: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. تغيير سياسة التنفيذ قد يعرضك للمخاطر الأمنية الموضحة في موضوع التعليمات about_Execution_Policies في http://go.microsoft.com/fwlink/?LinkID=135170. هل تريد تغيير نهج التنفيذ؟ [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> الميزة هي أنه ليس عليك التبديل بين نوافذ المحرر ونوافذ سطر الأوامر + + + + + +ابدأ بيئتك الافتراضية بتشغيل: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +تذكر أن تستبدل `myvenv` باسم `virtualenv` الذي اخترته! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +سوف تعرف أنك قمت بتفعيل الـ `virtualenv` الخاصة بك عندما ترى أن الموجه في وحدة التحكم الخاصة بك مسبوقاً بـ `(myvenv)`. + +عند العمل ضمن بيئة افتراضية، سيشير `python` تلقائياً إلى الإصدار الصحيح حيث يمكنك استخدام `python` بدلاً من `python3`. + +حسنا، لدينا كافة التبعيات الهامة في المكان. وأخيراً يمكننا تثبيت جانغو! + +## تثبيت جانغو {#django} + +الآن بما انه لديك `virtualenv` مشغل، يمكنك تثبيت جانغو. + +قبل أن نفعل ذلك، يجب علينا التأكد من لدينا أحدث إصدار من `pip`، البرامج التي نستخدمها لتثبيت جانغو: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### تثبيت الحزم مع المتطلبات + +ملف المتطلبات يحتفظ بقائمة من التبعيات ليتم تثبيتها باستخدام `pip install`: + +أولاً قم بإنشاء ملف `requirements.txt` داخل مجلد `djangogirls` باستخدام محرر التعليمات البرمجية الذي قمت بتثبيته سابقاً. تفعل ذلك عن طريق فتح ملف جديد في محرر التعليمات البرمجية وحفظه بإسم `requirements.txt` في مجلد `djangogirls/` سيبدو الدليل الخاص بك هكذا: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +في ملف `djangogirls/requirements.txt` يجب عليك إضافة النص التالي: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +الآن، قم بتشغيل `pip install -r requirements.txt` لتثبيت جانغو. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). إذا كان كذالك، يرجى التفكير في استخدام مكان آخر دون مسافات، علامات نطقية أو أحرف خاصة (اقتراح: `C:\djangogirls`). أنشئ virtualenv جديدة في الدليل الجديد، ثم إحذف القديمة وحاول تنفيذ الأمر أعلاه مرة أخرى. (نقل دليل virtualenv لن يعمل لأن virtualenv يستخدم مسارات مطلقة.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> إذا كنت تحصل على خطأ عند استدعاء برنامج pip على أوبونتو 12.04 الرجاء تشغيل `python -m pip install -U --force-reinstall pip` لإصلاح تثبيت برنامج pip في virtualenv. + + + +هذا كل شيء! أنت الآن على استعداد لإنشاء تطبيق جانغو (أخيرا)! \ No newline at end of file diff --git a/ar-SA/django_models/README.md b/ar-SA/django_models/README.md new file mode 100644 index 00000000000..4f817ffdb62 --- /dev/null +++ b/ar-SA/django_models/README.md @@ -0,0 +1,201 @@ +# نماذج جانغو + +ما نريد أن نخلق الآن هو شيء من شأنه أن يخزن جميع المشاركات في مدونتنا. ولكن لكي نكون قادرين على القيام بذلك، نحتاج إلى الحديث قليلا عن الأشياء المسماة `objects`. + +## الكائنات + +هناك مفهوم في البرمجة يسمى `object-oriented programming`. والفكرة هي أنه بدلاً من كتابة كل شيء كتسلسل ممل من تعليمات البرمجة، يمكننا نمذجة الأشياء وتحديد كيفية تفاعلها مع بعضها البعض. + +ما هو الكائن؟ عبارة عن مجموعة من الخصائص واﻹجراءات. قد تبدو غريبة في البداية، لكن سنقدم لكم المثال التالي. + +إذا أردنا نمذجة قط، سنقوم بإنشاء كائن `Cat` يحتوي على بعض الخصائص مثل `اللون`, `العمر`, `المزاج` (مثل جيد أو سيئ، أو النعاس;))، و `المالك`(التي يمكن أن تسند إلى الكائن `الشخص` – أو ربما، في حالة قط ضآل، يمكن أن تكون الخاصية فارغة). + +ثم يحتوي `القط` على بعض الإجراءات: `مواء` أو `خدش` أو `إطعام` (وفي بعض الحالات نعطي القط ` طعام القط`، والتي يمكن أن تكون كائن منفصل مع خصائص، مثل `المذاق`). + + القط + -------- + اللون + العمر + المزاج + المالك + مواء() + خدش() + إطعام(طعام_القط) + + + CatFood + -------- + taste + + +مبدأيا الفكرة هي وصف الأشياء الحقيقة بإستعمال البرمجة بالخصائص(تسمى` خصائص الشيئ`) و الإجراءات (تسمى`الأساليب`). + +كيف سننشئ مشاركات المدونة بعد ذلك؟ نحن نريد بناء مدونة، أليس كذلك؟ + +نحن بحاجة إلى الإجابة على السؤال: ما هي وظيفة المدونة؟ ما هي الخصائص التي يجب ان تحملها؟ + +حسنا، بالتأكيد لدينا مشاركة في مدونتنا تحتاج بعض النصوص مع محتوى وعنوان، أليس كذلك؟ سيكون جيدا ايضا معرفة من كتبها ، لذا نحن بحاجة لكاتب. وأخيرا نود معرفة متى تم إنشاء ونشر المشاركة. + + Post + -------- + title + text + author + created_date + published_date + + +ما نوع الأشياء التي يمكن إجراؤها على مشاركة في المدونة؟ سيكون من الجميل أن يكون لديك بعض `method` التي تنشر المشاركة، أليس كذلك؟ + +لذلك سوف نحتاج إلى أسلوب `publish`. + +نظراً لأننا نعرف ما نريد أن نحققه، دعونا نبدأ النمذجة في جانغو! + +## نماذج جانغو + +بمعرفة ما هو الكائن ، يمكننا انشاء نمودج للمشاركة على مدونتنا. + +النموذج في جانغو هو كائن من نوع خاص يتم حفظه في `database`. قاعدة بيانات هي مجموعة من البيانات. هذا هو المكان الذي ستحفض فيه معلومات حول المستخدمين ،مشاركاتك ومدونتك. سيتم استخدام قاعدة بيانات SQLite لتخزين البيانات الخاصة بنا. هذه قاعدة البيانات الإفتراضية الخاصة بجانغو-- سوف تكون كافية بالنسبة لنا الآن. + +يمكنك التفكير في نموذج في قاعدة البيانات كجدول مع الصفوف (بيانات) والأعمدة (الحقول). + +### إنشاء تطبيق + +لإبقاء كل شيء مرتباً، سننشئ تطبيق منفصل داخل مشروعنا. انه من الجميل ان يكون كل شيء مرتب من البداية. لإنشاء تطبيق نحن بحاجة إلى تشغيل الأمر التالي في وحدة التحكم (من `djangogirls` حيث يوجد الملف `manage.py`): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +ستلاحظ أنه تم إنشاء دليل `blog` جديد ويحتوي على عدد من الملفات الآن. يجب أن تبدو الدلائل والملفات في مشروعنا كما يلي: + + djangogirls + ├── blog + │ ├── admin.py + │ ├── apps.py + │ ├── __init__.py + │ ├── migrations + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │ ├── __init__.py + │ ├── settings.py + │ ├── urls.py + │ └── wsgi.py + ├── myvenv + │ └── ... + └── requirements.txt + + + +بعد إنشاء التطبيق، نحتاج أيضا أن نقول لدجانغو أنه ينبغي استخدامه. نقوم بذلك في الملف `mysite/settings.py` -- قم بفتحه في محرر التعليمات البرمجية الخاص بك. نحن بحاجة إلى العثور على `INSTALLED_APPS` وإضافة سطر يحتوي على `'blog.apps.BlogConfig',` فقط فوق `]`. المنتج النهائي ينبغي أن يبدو هكذا: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### إنشاء نمودج مشاركة في المدونة + +في ملف `blog/models.py` نحدد كافة كائنات تسمى `Models`--وهذا هو المكان الذي سنحدد فيه مشاركات مدونتنا. + +دعونا نفتح `blog/models.py` في محرر التعليمات البرمجية، وإزالة كل شيء منه، وكتابة التعليمات البرمجية مثل هذا: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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" (اختصارا ل "double-underscore"). + +يبدو مخيفا، أليس كذلك؟ ولكن لا تقلق--سوف نشرح ماذا تعني هذه السطور! + +جميع الخطوط بدءاً `from` أو `import` هي سطور تضيف بعض أجزاء من ملفات أخرى. بدلاً من نسخ ولصق نفس الأشياء في كل ملف، يمكن أن ندرج بعض الأجزاء مع `من... import ...`. + +`class Post(models.Model):` --هذا السطر يحدد نموذج لدينا (و هو`الكائن`). + +- `class` هي كلمة أساسية خاصة التي تشير إلى أنه علينا تحديد كائن. +- `Post` هو اسم نموذجنا. ويمكننا أن نعطيه اسما مختلفا (ولكن يجب علينا تجنب الأحرف الخاصة والمسافاة). ابدأ دائما بإسم فئة مع حرف كبير. +- `models.Model` يعني أن المشاركة هي نموذج لجانغو، لذلك دجانغو يعرف أنه يجب حفظها في قاعدة البيانات. + +والآن علينا أن نحدد الخصائص التي كنا نتحدث عنها`title`, `text`, `created_date`, `published_date` و `author`. للقيام بذالك نحن بحاجة إلى تحديد نوع كل حقل (النص؟ رقم؟ تاريخ؟ علاقة لكائن آخر، مثل مستخدم) + +- `models.CharField` –--وهكذا يمكنك تحديد نص مع عدد محدود من الأحرف. +- `models.TextField` – هذا لنص طويل دون حد. يبدو مثاليا لمدونة لمشاركة المحتوى، أليس كذلك؟ +- `models.DateTimeField` --هذا هو التاريخ والوقت. +- `models.ForeignKey`--وهذا ارتباط إلى نموذج آخر. + +نحن لن شرح كل شيء من التعليمات البرمجية هنا لأنه سوف يستغرق الكثير من الوقت. ينبغي أن نلقي نظرة على وثائق جانغو إذا كنت ترغب في معرفة المزيد عن حقول النموذج وكيفية تحديد الأشياء غير تلك المذكورة أعلاه (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +وماذا عن `def publish(self):`؟ هذا هو بالضبط الأسلوب `publish` الذي كنا نتحدث عنه. `def` يعني أن هذا أسلوب دالة و `publish` اسم الأسلوب. يمكنك تغيير اسم الأسلوب إذا أردت. حكم التسمية أن نستخدم حروف صغيرة وتسطيرات أسفل السطر بدلاً من المسافات. على سبيل المثال، يمكن استدعاء أسلوب والذي يقوم بحساب متوسط السعر `calculate_average_price`. + +أساليب كثيرا ما `return` شيئا. هناك مثال على ذلك في أسلوب `__str__`. في هذا السيناريو، عندما ندعو `__str__()` سوف تحصل على نص (**string**) مع عنوان البريد. + +كما لاحظ أن كلا `def publish(self):` و `def __str__(self):` يتم فصلها داخل فئتنا. نظراً لأن بايثون حساسة للمسافة البيضاء، نحن بحاجة لوضع مسافة بادئة لأساليب عملنا داخل الفئة. بخلاف ذلك، الأساليب التي لا تنتمي إلى الفئة، ويمكنك الحصول على بعض السلوك الغير متوقع. + +إذا كان هناك شيء لا يزال غير واضح حول النماذج، لا تتردد بسؤال المدرب الخاص بك! نحن نعلم أنها معقدة، لا سيما عندما كنت تتعلم ما الأشياء والمهام في نفس الوقت. ولكن نأمل أن يبدو أقل سحرا قليلا الآن! + +### إنشاء جداول للنماذج في قاعدة البيانات الخاصة بك + +الخطوة الأخيرة هنا لإضافة نموذجنا الجديد إلى قاعدة البيانات الخاصة بنا. أولاً يجب أن تجعل جانغو يعرف أن لدينا بعض التغييرات في نموذجنا. (لقد أنشئناه للتو!) إذهب إلى إطار وحدة التحكم الخاصة بك واكتب `python manage.py makemigrations blog`. ستبدو كالشكل التالي: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**ملاحظة:** تذكر أن تقوم بحفظ الملفات التي يمكنك تحريرها. وبخلاف ذلك، سيقوم الكمبيوتر بتنفيد النسخة السابقة والتي قد تعطيك رسائل خطأ غير متوقعة. + +أعدت دجانغو ملف ترحيل لنا وعلينا الآن أن نطبقه على قاعدة البيانات الخاصة بنا. اكتب `python manage.py migrate blog` ويكون الإخراج كما يلي: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +يا هلا! الآن لدينا نموذج آخر في قاعدة بياناتنا! سيكون من الجميل أن نراه ، اليس كذالك؟ انتقل إلى الفصل التالي لمعرفة الشكل الذي تبدو عليه مشاركتك! \ No newline at end of file diff --git a/ar-SA/django_orm/README.md b/ar-SA/django_orm/README.md new file mode 100644 index 00000000000..983e701b9e6 --- /dev/null +++ b/ar-SA/django_orm/README.md @@ -0,0 +1,221 @@ +# ORM جانغو و Querysets + +في هذا الفصل سوف تتعلم كيف تتصل جانغو بقاعدة البيانات وتقوم بتخزين البيانات فيها. دعونا نغوص في الشرح! + +## ما هو QuerySet؟ + +QuerySet هو، في جوهره، قائمة الكائنات من نموذج معين. QuerySet تسمح لك بقراءة البيانات من قاعدة البيانات، وتصفيها وتطلبها. + +من السهل التعلم عبر الأمثلة ، دعونا نجرب ذالك. هيا بنا؟ + +## Django shell + +إفتح وحدة التحكم المحلية الخاصة بك (ليس على PythonAnywhere) واكتب هذا الأمر: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +التأثير يجب أن يكون مثل: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +أنت الآن في وحدة التحكم التفاعلية لجانغو. إنها تماماً مثل موجه بايثون، ولكن مع بعض سحر جانغو الإضافي. :) يمكنك استخدام جميع أوامر بايثون هنا أيضاً. + +### كل الكائنات + +دعونا نحاول عرض جميع المشاركات لدينا أولاً. يمكنك القيام بذلك باستخدام الأمر التالي: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +اووبس! ظهر خطأ. يقول لنا أنه لا يوجد أي مشاركة. هذا صحيح لقد نسينا استيراده أولا! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +نستورد النموذج `Post` من`blog.models`. لنحاول عرض جميع المشاركات مرة أخرى: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +هذه قائمة باالمشاركات التي أنشأنا في وقت سابق! قمنا بإنشاء هذه المشاركات باستخدام واجهة المشرف جانغو. ولكن الآن نحن نريد انشاء مشاركات جديدة باستخدام بيثون، فكيف نفعل ذلك؟ + +### إنشاء كائن + +هذه هي الطريقة التي تقوم بها بإنشاء مشاركة كائن جديد في قاعدة البيانات: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +ولكن لدينا عنصر واحد في عداد المفقودين هنا `me`. نحن بحاجة إلى تمرير مثيل من نموذج `User` كمؤلف. كيف نفعل ذلك؟ + +دعونا نسترد نموذج المستخدم الأول: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +اية مستخدمين لدينا في قاعدة البيانات الخاصة بنا؟ جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +هذا هو المستخدم المتميز الذي أنشأناه سابقاً! دعونا نحصل على مثيل للمستخدم الآن (قم بضبط هذا السطر لاستخدام اسم المستخدم الخاص بك): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +كما ترون، نحن الآن `نحصل على` `مستخدم` مع `اسم مستخدم` يساوي 'ola'. رائع! + +الآن يمكننا أخيرا إنشاء مشاركة: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +يا هلا! هل تريد التحقق من ما إذا كان يعمل؟ + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +هاهي ذا! مشاركة آخرى في القائمة! + +### إضافة المزيد من المشاركات + +يمكنك الآن الحصول على القليل من المرح وإضافة المزيد من المشاركات لنرى كيف يعمل. أضف اثنين أو ثلاثة آخرين ثم انتقل إلى الجزء التالي. + +### تصفية الكائنات + +جزء كبير من QuerySets هو القدرة على تصفيتهم. لنفترض أننا نريد العثور على جميع المشاركات التي قام المستخدم ola بتأليفها. سنقوم باستخدام `filter` بدلاً من `all` في `Post.objects.all()`. بين قوسين نوضح ما هي الشروط التدوينة تحتاج إلى تلبية في نهاية المطاف في queryset لدينا. وفي حالتنا، الشرط أن `author` يجب أن يكون متساوي مع `me`. طريقة كتابتها في دجانغو `author=me`. الأن قطعتنا من الكود تبدو بهذا الشكل: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +أو ربما نريد أن نرى جميع المشاركات التي تحتوي على كلمة 'title' في الحقل `title`؟ + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **ملاحظة** هناك شرطتين أسفل السطر (`_`) بين `title` و `contains`. يستخدم ORM دجانغو هذه القاعدة لفصل أسماء الحقول ("title") والعمليات أو الفلاتر ("contains"). إذا قمت باستخدام تسطير واحد فقط، سوف تحصل على خطأ مثل "FieldError: Cannot resolve keyword title_contains". + +يمكنك أيضا الحصول على قائمة بجميع المشاركات المنشورة. علينا القيام بذلك بتصفية جميع المشاركات التي قد `published_date` في الماضي: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +للأسف، لم يتم نشر المشاركة التي أضفناها من وحدة تحكم بايثون بعد. ولكن يمكننا تغيير ذلك! احصل أولا على مثال لمشاركة نريد نشرها: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +ثم أنشرها باستخدام طريقة `publish`: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +الآن في محاولة للحصول على قائمة المشاركات المنشورة مرة أخرى (اضغط على مفتاح السهم لأعلى ثلاث مرات واضغط `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### العناصر الصادرة + +QuerySets تسمح لك أيضا بترتيب قائمة الكائنات. دعونا نحاول ترتيبها حسب الحقل `created_date`: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +يمكننا أيضا عكس الترتيب بإضافة `-` في البداية: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### الاستفسارات المعقدة من خلال سلسلة الأساليب + +كما رأيت، بعض الطرق في `Post.objec` تعيد QuerySet. نفس الأساليب يمكن أيضاً استدعاؤها على QuerySet، وبعد ذلك ستعيد QuerySet جديدة. وهكذا، يمكنك الجمع بين تأثيرها من خلال **سلسلة** بعضها البعض: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +هذا حقا قوي ويتيح لك كتابة استفسارات معقدة جدا. + +رائع! أنت الآن جاهز للجزء التالي! لإغلاق الشل shell، اكتب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/ar-SA/django_start_project/README.md b/ar-SA/django_start_project/README.md new file mode 100644 index 00000000000..51e0cc45adf --- /dev/null +++ b/ar-SA/django_start_project/README.md @@ -0,0 +1,260 @@ +# مشروعك الأول في جانغو! + +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots). +> +> جزء من هذا القسم يستند [django-marcador tutorial](http://django-marcador.keimlink.de/) المرخص لها بمرخصة بموجب المشاع الإبداعي   إسناد-على غرار 4.0 الترخيص الدولي. البرنامج التعليمي django-marcador حقوق الطبع والنشر من قبل Markus Zapke-Gründemann وآخرون. + +سنقوم بإنشاء مدونة صغيرة! + +الخطوة الأولى هي إنشاء مشروع جانغو جديد. في الأساس، وهذا يعني أننا سوف نشغل بعض البرامج النصية التي تقدمها جانغو والتي من شأنها أن تخلق الهيكل العظمي لمشروع دجانغو بالنسبة لنا. هذه مجرد حفنة من الدلائل والملفات التي سوف نستخدمها في وقت لاحق. + +أسماء بعض الملفات والدلائل مهمة جداً لجانغو. يجب عدم إعادة تسمية الملفات التي نحن على وشك إنشائها. نقلهم إلى مكان مختلف ليست فكرة جيدة. جانغو تحتاج إلى الحفاظ على بنية معينة لتكون قادرة على العثور على أشياء مهمة. + +> تذكر أن تقوم بتشغيل كل شيء في virtualenv. إذا كنت لا ترى بادئة `(myvenv)` في وحدة التحكم الخاصة بك، تحتاج إلى تنشيط virtualenv الخاص بك. قمنا بشرح طريقة فعل ذالك في **Django installation** في قسم **Working with virtualenv**. كتابة `myvenv\Scripts\activate` في وندوز ، او `source myvenv/bin/activate` في ماك ولينكس سيقوم لك بذالك. + + + +في وحدة التحكم الخاصة بك ماكنتوش أو لينكس، يجب أن تقوم بتشغيل الأمر التالي. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> الفاصلة `.` أمر بالغ الأهمية لأنه يخبر السكريبت لتثبيت دجانغو في الدليل الحالي الخاص بك (`.` الفاصلة هي إشارة قصيرة). +> +> **ملاحظة** عند كتابة الأمر أعلاه، تذكر أن تكتب فقط الجزء الذي يبدأ ب `django-admin`. الجزء `(myvenv) ~/djangogirls$` الموضح هنا هو مجرد مثال من الموجه الذي سيدعو المدخلات الخاصة بك على سطر الأوامر الخاص بك. + + + + + +في وحدة التحكم الخاصة بوندوز، يجب أن تقوم بتشغيل الأمر التالي. **Don't forget to add the period (or dot) `.` at the end!**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> الفاصلة `.` أمر بالغ الأهمية لأنه يخبر السكريبت لتثبيت دجانغو في الدليل الحالي الخاص بك (`.` الفاصلة هي إشارة قصيرة). +> +> **ملاحظة** عند كتابة الأمر أعلاه، تذكر أن تكتب فقط الجزء الذي يبدأ ب `django-admin.py`. الجزء (myvenv) C:\Users\Name\djangogirls>` الموضح هنا هو مجرد مثال من الموجه الذي سيدعو المدخلات الخاصة بك على سطر الأوامر الخاص بك. + + + +`django-admin.py` هو البرنامج النصي الذي سينشئ الدلائل والملفات بالنسبة لك. يجب أن يكون لديك الآن هيكل دليل يشبه هذا: + + djangogirls + ├── manage.py + ├── mysite + │ ├── __init__.py + │ ├── settings.py + │ ├── urls.py + │ └── wsgi.py + ├── myvenv + │ └── ... + └── requirements.txt + + +> **ملاحظة** في بنية الدليل، سترى أيضا `venv` الذي أنشأناه من قبل. + +`manage.py` هو سكريبت يساعد في إدارة الموقع. مع أنه سوف نتمكن من (ضمن أمور أخرى) لبدء تشغيل خادم الويب على جهاز الكمبيوتر بدون تثبيت أي شيء آخر. + +يحتوي الملف `settings.py` على إعدادات موقعك. + +تذكر عندما تكلمنا عن ساعي البريد الذي يبحث اين يرمي الرسائل? `urls.py` ملف يحتوي على قائمة أنماط مستخدمة من قبل `urlresolver`. + +دعونا نتجاهل الملفات الأخرى في الوقت الراهن فنحن لن نغييرها. الشيء الوحيد الذي يجب تذكره هو عدم حذفها عن طريق الصدفة! + +## تغيير الإعدادات + +دعونا نجري بعض التغييرات في `mysite/settings.py`. قم بفتح الملف باستخدام محرر التعليمات البرمجية يالذي قمنا بتثبيته في وقت سابق. + +**ملاحظة**: ضع في اعتبارك أن `settings.py` هو ملف عادي، مثل أي ملف آخر. يمكنك فتحه من داخل محرر التعليمات البرمجية، وذلك باستخدام "ملف > فتح" قائمة الإجراأت. سيؤدي هذا بك إلى الحصول على النافذة المعتادة التي يمكنك فيها الانتقال إلى ملف `settings.py` وتحديده. بدلا من ذلك، يمكنك فتح الملف عن طريق الانتقال إلى مجلد djangogirls على سطح المكتب الخاص بك والنقر بزر الماوس الأيمن عليه. ثم، حدد محرر التعليمات البرمجية الخاصة بك من القائمة. اختيار المحرر مهم كما قد يكون لديك برامج أخرى مثبتة يمكنها فتح الملف ولكن لن تسمح لك بتحريره. + +سيكون من الجميل أن يكون الوقت صحيح على موقعنا على الانترنت. اذهب الى [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) وانسخ الوقت في منطقتك الزمنية (TZ) (e.g. `Europe/Berlin`). + +في `settings.py`، أعثر على السطر الذي يحتوي على `TIME_ZONE` وعدله لاختيار المنطقة الزمنية الخاصة بك. على سبيل المثال: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +رمز اللغة يتكون من اللغة، مثل `en` للغة الإنجليزية أو `de` للألمانية، ورمز البلد، مثل `de` لألمانيا أو `ch` لسويسرا. إذا لم تكن اللغة الإنجليزية لغتك الأصلية، يمكنك إضافة هذا لتغيير الأزرار والإشعارات الافتراضية من جانغو لتكون بلغتك. لذلك سيكون لديك زر "إلغاء" ترجم إلى اللغة التي حددتها هنا. [جانغو يأتي مع الكثير من الترجمات المعدة](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +إذا كنت تريد لغة مختلفة، قم بتغيير رمز اللغة بتغيير السطر التالي: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +سوف نحتاج أيضا إلى إضافة مسار للملفات الثابتة. ( سوف نعرف كل شيء عن الملفات الثابتة والمغلقة في وقت لاحق في البرنامج التعليمي). الانتقال إلى أسفل إلى *end* الملف، وتحت `STATIC_URL`، أضف وحدة جديدة تسمى `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +عندما يكون `DEBUG` هو `True` و `ALLOWED_HOSTS فارغ، يتم التحقق من المضيف مع ['localhost', '127.0.0.1', '[::1]']`. هذا لن يطابق اسم المضيف لدينا على PythonAnywhere بمجرد نشر التطبيق لدينا لذلك سوف نقوم بتغيير الإعداد التالي: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **ملاحظة**: إذا كنت تستخدم Chromebook، أضف هذا السطر في الجزء السفلي من الملف settings.py: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> أضف أيضا `.amazonaws.com` إلى `ALLOWED_HOSTS` إذا كنت تستخدم Cloud9 +> +> إذا كنت تستضيف مشروعك على `Glitch.com`، دعونا نحمي مفتاح جانغو السري الذي يحتاج أن يبقى سرياً (عدا ذلك، أي شخص يعيد تعديل مشروعك يمكنه رؤيته): +> +> - أولا، سنقوم بإنشاء مفتاح سري عشوائي. افتح المحطة الطرفية Glitch مرة أخرى، واكتب الأمر التالي: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> هذا يجب أن يعرض سلسلة عشوائية طويلة، مثالية لاستخدامها كمفتاح سري لموقع جانغو الجديد الخاص بك. سوف نلصق هذا المفتاح الآن في ملف `.env` الذي سيقوم Glitch بعرضه لك فقط إذا كنت مالك الموقع. +> +> - أنشئ ملف `.env` في جذر مشروعك وأضف الخاصية التالية فيه: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # هنا، داخل الاقتباس الفردي، يمكنك قطع ولصق المفتاح العشوائي المنشأ أعلاه +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - ثم قم بتحديث ملف إعدادات جانغو لحقن هذه القيمة السرية وتعيين اسم موقع جانغو: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - وفي الأسفل قليلاً في نفس الملف، نقوم بحقن اسم موقع Glitch الجديد الخاص بك: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> قيمة `PROJECT_DOMAIN` يتم إنشاؤها تلقائيًا بواسطة Glitch. سوف تتوافق مع اسم مشروعك. + +## إعداد قاعدة البيانات + +هناك الكثير من برامج قواعد البيانات المختلفة التي يمكنها تخزين البيانات لموقعك. سنستخدم الإعداد الافتراضي، `sqlite3`. + +تم إعداد هذا بالفعل في هذا الجزء الخاص بك من الملف `mysite/settings.py`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +لإنشاء قاعدة بيانات مدونتنا، دعونا تشغل الأمر التالي في وحدة التحكم: `python manage.py migrate`(نحن بحاجة إلى أن تكون في الدليل `djangogirls` الذي يحتوي على الملف `manage.py`. اذا مر كل شيء على ما يرام، سترى شيئا مثل هذا: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +ها قد انتهينا! حان الوقت لتشغيل خادم الويب ومعرفة ما إذا كان موقعنا يعمل! + +## بدء تشغيل خادم الويب + +يجب أن تكون في الدليل الذي يحتوي على ملف `manage.py`(دليل `djangogirls`). في وحدة التحكم، يمكننا أن نبدأ خادم الويب بتشغيل `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +إذا كنت في كروم بوك، استخدم هذا الأمر بدلاً من ذلك: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +أو هذا إذا كنت تستخدم Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +إذا كنت على ويندوز، و فشل هذا مع `UnicodeDecodeError`, ، استخدم هذا الأمر بدلاً من ذلك: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +الآن تحتاج إلى التحقق من أن موقعك قيد التشغيل. افتح المتصفح الخاص بك (Firefox, Chrome, Safari, Internet Explorer أو أي شيء تستخدمه) وأدخل هذا العنوان: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +إذا كنت تستخدم Chromebook و Cloud9، بدلاً من ذلك، انقر فوق عنوان URL في النافذة المنبثقة التي كان ينبغي أن تظهر في الزاوية اليمنى العليا من نافذة الأوامر حيث يعمل خادم الويب. سيبدو عنوان URL شيئًا مثل: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +أو على Glitch: + + https://name-of-your-glitch-project.glitch.me + + +تهانينا! لقد قمت بإنشاء موقعك الأول وتشغيله باستخدام خادم ويب! أليس هذا رائعاً؟ + +![تم التثبيت بنجاح!](images/install_worked.png) + +لاحظ أن نافذة الأوامر يمكنها تشغيل شيء واحد فقط في كل مرة، وأن نافذة الأوامر التي فتحتها في وقت سابق تقوم بتشغيل خادم الويب. طالما أن خادم الويب يعمل وينتظر طلبات إضافية واردة ، ستقبل المحطة الطرفية نصا جديدا ولكنها لن تنفذ أوامر جديدة. + +> لقد استعرضنا كيف تعمل خادمات الويب في الفصل **How the Internet works**. + +لكتابة أوامر إضافية أثناء تشغيل خادم الويب، قم بفتح نافذة طرفية جديدة وتفعيل virtualenv الخاصة بك -- لمراجعة التعليمات حول كيفية فتح نافذة طرفية ثانية، انظر [Introduction to the command line](../intro_to_command_line/README.md). لإيقاف خادم الويب، قم بالتبديل مرة أخرى إلى النافذة التي يعمل فيها واضغط على CTRL+C - مفاتيح التحكم و C معا (على ويندوز، قد تضطر إلى الضغط على Ctrl+Break). + +مستعد للخطوة التالية؟ لقد حان الوقت لإنشاء بعض المحتوى! \ No newline at end of file diff --git a/ar-SA/django_templates/README.md b/ar-SA/django_templates/README.md new file mode 100644 index 00000000000..15347850fe5 --- /dev/null +++ b/ar-SA/django_templates/README.md @@ -0,0 +1,108 @@ +# قوالب دجانغو + +حان الوقت لكي نظهر بعض المعلومات! جانغو يعطينا بعضا من شعارات القوالب المفيدة المثبتة فية. + +## ما هي شعارات القوالب؟ + +كما تعرف في لغة الHTML لا يمكنك كتابة كود مكتوب بلغة Python وذلك لأن متصفحات الانترنت لا تفهمة. المتصفحات تفهم الHTML فقط. نحن نعلم أن الHTML نوعا ما جامدة لكن الPython أكثر ديناميكية. + +**Django template tags** تسمح لنا بنقل أشياء مثل بيثون إلى HTML، حتى نتمكن من بناء مواقع ديناميكية بشكل أسرع. رائع! + +## عرض قالب قائمة المشاركات + +في الفصل السابق، قدمنا لقالبنا قائمة بالمشاركات في متغير `posts`. الآن سوف نقوم بعرضه في HTML. + +لطباعة متغير في قوالب جانغو، نحن نستخدم أقواس مزدوجة مع اسم المتغير في الداخل، هكذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +جرب هذا في قالبك `blog/templates/blog/post_list.html`. قم بفتحه في محرر التعليمات البرمجية، واستبدل كل شي من `
` الثاني إلى `
` الثالث بـ `{{ posts }}`. قم بحفظ الملف، وقم بتحديث الصفحة لمشاهدة النتائج: + +![الرقم 13.1](images/step1.png) + +كما ترون، كل ما لدينا هو هذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +هذا يعني أن جانغو يفهم ذلك كقائمة من الكائنات. هل تتذكر من **Introduction to Python** كيف نضهر القوائم؟ نعم، مع حلقات! في قالب جانغو يمكنك القيام بها هكذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +جرب هذا في قالبك. + +![الرقم 13.2](images/step2.png) + +إنه كان مجديًا! ولكننا نريد أن يتم عرض المشاركات مثل المشاركات الثابتة التي أنشأناها سابقا في فصل **مقدمة إلى HTML**. يمكنك خلط علامات HTML والقالب. `body` سيبدو هكذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %} كل شيء تضعه بين `{% for %}` و `{% endfor %}` سوف يتكرر لكل كائن في القائمة. حدث الصفحة:{% endraw %} + +![الرقم 13.3](images/step3.png) + +هل لاحظت أننا استخدمنا تدوين مختلف قليلا هذه المرة (`{{ post.title }}` او `{{ post.text }})`؟ يمكننا الوصول إلى البيانات في كل حقل من الحقول المعرفة في نموذج `Post`. ايضا `|linebreaksbr` يربط نص المشاركات من خلال مرشح لتحويل فواصل الأسطر إلى فقرات. + +## شيء واحد آخر + +سيكون جيدا معرفة ما إذا كان موقع الويب الخاص بك لا يزال يعمل على شبكة الإنترنت العامة، اليس كذالك؟ دعونا نحاول نشره في PythonAnywhere مرة أخرى. هنا خلاصة للخطوات… + +* أولاً، ادفع التعليمات البرمجية الخاصة بك إلى Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* افتح [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) واذهب الى **Bash console** او افتح واحدة جديدة وشغل هذا الأمر: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(تذكر أن تستبدل `` بالمجال الفرعي لـ PythonAnywhere الفعلي، بدون أقواس الزاوية. ) + +* وأخيراً، انتقل إلى ["Web" page](https://www.pythonanywhere.com/web_app_setup/) واضغط على **Reload** في تطبيق الويب الخاص بك. (للوصول إلى صفحات PythonAnywhere الأخرى من وحدة التحكم ، استخدم زر القائمة في الزاوية اليمنى العلوية. يجب أن يكون تحديثك مباشرًا على https://subdomain.pythonanywhere.com -- تحقق من ذلك في المتصفح! إذا كانت مشاركات المدونة على موقع PythonAnywhere لا تتطابق مع المشاركات التي تظهر على المدونة المستضافة على الخادم المحلي، فلا بأس بذالك. قواعد البيانات على جهاز الكمبيوتر المحلي وبايثون في أي مكان لا يتزامنان مع بقية الملفات الخاصة بك. + +تهانينا! الآن امضي قدما وحاول إضافة مشاركة جديدة عبر إدارة جانغو الخاصة بك (تذكر من إضافة published_date!) تأكد من أنك في صفحة المشرف لجانغو لموقع pythonanywhere الخاص بك، https://subdomain.pythonanywhere.com/admin. ثم حدث الصفحة لمعرفة ما إذا كانت المشاركة تظهر هناك أم لا. + +تعمل مثل السحر؟ نحن فخورون! ابتعدوا قليلا عن جهاز الكمبيوتر الخاص بك - لقد حصلت على استراحة. :) + +![الشكل 13.4](images/donut.png) \ No newline at end of file diff --git a/ar-SA/django_urls/README.md b/ar-SA/django_urls/README.md new file mode 100644 index 00000000000..6821d466b31 --- /dev/null +++ b/ar-SA/django_urls/README.md @@ -0,0 +1,103 @@ +# روابط جانغو + +نحن على وشك بناء صفحتنا الأولى على الإنترنت: الصفحة الرئيسية لمدونتك! ولكن أولاً، دعونا نتعلم قليلاً عن "روابط مواقع جانغو". + +## ما هو الرابط (URL) ؟ + +ببساطة الرابط (URL) هو عنوان صفحة الويب. يمكنك أن ترى عنوان الرابط (URL) في كل مرة تقوم بزيارة الموقع على شبكة الإنترنت --إنها مرئية في شريط العناوين في المتصفح الخاص بك. (نعم! `127.0.0.1:8000` هو عنوان الرابط (URL)! و `https://djangogirls.org` أيضا الرابط (URL)) + +![عنوان صفحة الويب](images/url.png) + +كل صفحة على شبكة الإنترنت تحتاج إلى عنوان رابط (URL) خاص بها. بهذه الطريقة يستطيع تطبيقك ان يعلم ماذا يفتح للمستخدم الذي فتح الرابط. في جانغو نستخدم ما يسمى `URLconf` (URL configuration). URLconf هو مجموعة من الأنماط التي ستحاول جانغو مطابقتها مع عنوان URL المطلوب للعثور على طريقة العرض الصحيح. + +## كيف تعمل عناوين Url في جانغو؟ + +دعونا نفتح الملف `mysite/urls.py` في محرر التعليمات البرمجية الخاصة بك للاختيار ونرى ما يبدو عليه: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +كما ترون، جانغو قد وضعت بالفعل شيء هنا بالنسبة لنا. + +الخطوط بين علامات الاقتباس الثلاثي (`'' '` أو `"""`) تسمى docstrings – ييمكنك كتابتها في أعلى ملف أو فئة أو طريقة لوصف ما يفعله. هي لا تعمل عبر بايثون. + +عنوان URL المشرف، الذي زرته في الفصل السابق، موجود هنا: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +هذا السطر يعني أن لكل عنوان URL الذي يبدأ ب `admin/`، سوف تجد جانغو مقابله *view*. في هذه الحالة نحن ، نضع الكثير من روابط المدير ، لذالك هي ليست مجموعة كلها في هذا الملف الصغير ، انها اكثر قابلية للقراءة وانضف. + +## رابط جانغو الأول الخاص بك! + +حان الوقت لإنشاء أول عنوان URL لنا! نريد 'http://127.0.0.1:8000/' أن تكون الصفحة الرئيسية لمدونتنا وأن تعرض قائمة من المشاركات. + +نريد أيضا الاحتفاظ بالملف `mysite/urls.py` نظيف، حيث أننا سوف نسترد عناوين Url من تطبيق `blog` لدينا إلى الملف الرئيسي `mysite/urls.py`. + +امضي قدما ، واضف السطر الذي سيسترد `blog.urls`. ستحتاج أيضاً إلى تغيير السطر `from django.urls…` لأننا نستخدم الدالة `include` هنا، لذا ستحتاج إلى إضافة ذلك الاستيراد إلى السطر. + +ملف `mysite/urls.py` الخاص بك يجب أن يبدو مثل هذا: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +جانغو سيقوم الآن بإعادة توجيه كل ما يأتي إلى 'http://127.0.0.1:8000/' إلى `blog.urls` والبحث عن المزيد من التعليمات هناك. + +## blog.urls + +قم بإنشاء ملف فارغ جديد يسمى `urls.py` في الدليل `blog`، وقم بفتحه في محرر الكود. حسنًا! أضف هذين السطرين الأوليين: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +نحن هنا نستورد وظائف جانغو `path` وجميع الـ `views` من تطبيق الـ `blog`. (ليس لدينا أي شي حتى الآن، ولكننا سنصل إلى ذلك في دقيقة!) + +بعد ذلك، يمكننا إضافة أول نمط URL لدينا: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +كما ترون، نحن الآن نقوم بتعيين `view` يسمى `post_list` لعنوان URL الجذر. سيطابق نمط الرابط هذا سلسلة فارغة وسيتجاهل محلل URL جانغو اسم النطاق (i. ., http://127.0.0.1:8000/) الذي يبادئ مسار الرابط الكامل. سيخبر هذا النمط جانغو أن `views.post_list` هو المكان المناسب للذهاب إليه إذا دخل شخص ما موقعك على الويب على العنوان "http://127.0.0.1:8000/". + +الجزء الأخير، `name='post_list'`, هو اسم عنوان URL الذي سيتم استخدامه لتحديد طريقة العرض. وهذا يمكن أن يكون نفس اسم العرض ولكن أيضا يمكن أن يكون شيئا مختلفاً تماما. سنستخدم عناوين URLs المسماة لاحقا في المشروع، لذلك من المهم تسمية كل عنوان URL في التطبيق. يجب أن نحاول أيضا الحفاظ على أسماء عناوين URL فريدة وسهلة التذكر. + +إذا حاولت زيارة http://127.0.0.1:8000/ الآن، ستجد نوعا من رسائل الخطأ "صفحة ويب غير متوفرة". وذلك لأن الخادم (تذكر كتابة `runserver`?) لم يعد قيد التشغيل. ألق نظرة على نافذة وحدة تحكم الخادم لمعرفة السبب. + +![خطأ](images/error1.png) + +وحدة التحكم الخاصة بك تظهر خطأ، ولكن لا تقلق - إنه في الواقع مفيد جدا: إنه يخبرك أن **no attribute 'post_list'**. هذا هو اسم *view* الذي تحاول جانغو العثور عليه واستخدامه، ولكن لم نقم بإنشاءه بعد. في هذه المرحلة،`/admin/` لن يعمل أيضا. لا تقلق – سوف نصل إلى هناك. إذا رأيت رسالة خطأ مختلفة، حاول إعادة تشغيل خادم الويب الخاص بك. للقيام بذلك، في نافذة وحدة التحكم التي تقوم بتشغيل خادم الويب، أوقفها بالضغط على Ctrl+C (مفتاحي التحكم و C معا). على ويندوز، قد تضطر إلى الضغط على Ctrl+Break. ثم تحتاج إلى إعادة تشغيل خادم الويب عن طريق تشغيل أمر `python manage.py runserver`. + +> إذا كنت ترغب في معرفة المزيد عن URLconfs، انظر إلى الوثائق الرسمية: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/ar-SA/django_views/README.md b/ar-SA/django_views/README.md new file mode 100644 index 00000000000..c0d686f94d3 --- /dev/null +++ b/ar-SA/django_views/README.md @@ -0,0 +1,44 @@ +# وجهات نظر جانغو -وقت الإنشاء! + +حان الوقت للتخلص من الشوائب التي انشأناها في الفصل الأخير! :) + +*view* هو المكان الذي وضعنا فيه المنطق الخاص بتطبيقنا. وسوف تطلب معلومات من `model` قمت بإنشائها من قبل وتمريرها إلى `template`. سوف ننشئ قالب في الفصل التالي. وجهات النظر هي مجرد وظائف بيثون والتي هي اكثر تعقيد قليلا من التي قمنا بكتابتها في هذا الفصل **مقدمة بيثون**. + +Views توضع في الملف `views.py`. وسوف نضيف *views* الخاصة بنا الى `blog/views.py`. + +## blog/views.py + +حسنًا، دعونا نفتح هذا الملف في محرر التعليمات البرمجية الخاص بنا ونرى ما هو هناك: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +ليس هناك كثيرا من الأشياء هنا حتى الآن. + +تدكر ان الأسطر التي تبدأ ب`#` هي مجرد تعليقات وهذا يعني انها لن يتم استخدامها عبر بايثون. + +دعونا ننشء *view * كما يوحي التعليق. أضف الأسطر التالية أدناه: + +{% filename %}blog/views.py{% endfilename %} + +```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/وانظر ماذا لدينا. + +خطأ آخر! اقرأ ما يجري الآن: + +![خطأ](images/error.png) + +هذا يبين أن الملقم قيد التشغيل مرة أخرى، على الأقل، ولكن لا يزال يبدو وكأنه ليس على ما يرام أليس كذالك؟ لا تقلق، انها مجرد صفحة خطأ، لا تخف! تماما مثل رسائل الخطأ في وحدة التحكم، هذه في الواقع مفيدة جدا. يمكن أن تقرأ أن*TemplateDoesNotExist*. دعونا نصلح هذا الخطأ وننشئ قالب في الفصل التالي! + +> إعرف المزيد حول الـ views في جانغو من خلال قراءة الوثائق الرسمية: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/ar-SA/dynamic_data_in_templates/README.md b/ar-SA/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..657a180faff --- /dev/null +++ b/ar-SA/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# البيانات الديناميكية في قوالب + +لدينا قطع مختلفة في المكان: تم تحديد نموذج `Post` في `models.py`,، لدينا `post_list` في `views.py` والقالب المضاف. ولكن كيف سنظهر مشاركاتك في نموذج HTML ؟ لأن هذا ما نريد أن نفعله – اتخاذ بعض المحتويات (النماذج التي تم حفظها في قاعدة البيانات) وعرضها بشكل جميل ، اليس كذالك؟ + +وهذا بالضبط ما يفترض ب *views* القيام به: ربط النماذج والقوالب. وفي `post_list` *view* سوف نحتاج إلى أن النماذج التي نريد عرضها وتمريرها إلى القالب. في *view* نقرر اية (نمادج) سيتم عرضها في قالب. + +حسنا، كيف سوف نحقق ذلك؟ + +نحن بحاجة إلى فتح `blog/views.py`. وحتى الآن `post_list` *view* يبدو مثل هذا: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +تذكر عندما تحدثنا عن تضمين التعليمات البرمجية المكتوبة في ملفات مختلفة؟ الآن هي اللحظة التي يتعين علينا فيها ادخال النمودج الذي كتبنا في `models.py`. سوف نقوم بإضافة سطر `from .models import Post` مثل هذا: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +النقطة قبل `models` تعني *current directory* أو *current application*. `Views.py` و `models.py` في نفس الدليل. وهذا يعني أننا يمكن أن تستخدم `.` واسم الملف (بدون `.py`). ثم نقوم باستيراد اسم النموذج (`Post`). + +ولكن ما هي الخطوة التالية؟ لأخد المشاركات الفعلية للمدونة من `Post` نحن بحاجة إلى ما يسمى `QuerySet`. + +## QuerySet + +يجب ان تكون مألوف مع طريقة عمل QuerySets ، لقد تكلمنا عنهم في [Django ORM (QuerySets) chapter](../django_orm/README.md). + +لذا نريد الآن نشر مشاركات مدونة مرتبة حسب `published_date`، أليس كذلك؟ فعلنا ذلك بالفعل في فصل QuerySets! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +إذاً، دعونا نفتح الملف `blog/views.py` في محرر التعليمات البرمجية، ونضيف هذه القطعة من التعليمات البرمجية إلى الدالة `def post_list(request)` -- ولكن لا تنسى أولاً إضافة `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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 الخاص بنا في قائمة منشورات مدونتنا، لدينا شيئان متبقيان للقيام بهما: + +1. مرر الـ `posts` QuerySet إلى سياق القالب، عن طريق تغيير إستدعاء الدالة `render`. سنقوم بذلك الآن. +2. قم بتعديل القالب لعرض الـ `posts` QuerySet. سنقوم بتغطية هذا في فصل لاحق. + +يرجى ملاحظة أننا ننشئ *variable* لأعمالا QuerySet: `posts`.. عالج هذا كاسم QuerySet لدينا. من الآن فصاعدا يمكن أن نشير إليه بهذا الاسم. + +في دالة `render` لدينا معلمة واحد `request`(كل شيء نتلقاه من المستخدم عبر شبكة الإنترنت) والأخرى تعطي ملف القالب (`'blog/post_list.html'`). المعلمة الأخيرة، `{}`، هو مكان الذي يمكن أن نضيف فيه بعض الأشياء للقالب المطلوب استخدامه. نحن بحاجة لإعطائهم أسماء (ونحن سوف تلتزم ب `'posts'` الآن). :) ينبغي أن تبدو مثل هذا: `{'posts': posts}`. يرجى ملاحظة أن الجزء قبل `:` سلسلة; تحتاج إلى الإلتفاف مع علامات اقتباس: `''`. + +في النهاية ملف `blog/views.py` يجب اين يبدو مثل هذا: + +{% filename %}blog/views.py{% endfilename %} + +```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 في جانغو؟ يجب أن تنظر هنا: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/ar-SA/extend_your_application/README.md b/ar-SA/extend_your_application/README.md new file mode 100644 index 00000000000..5b126f6e577 --- /dev/null +++ b/ar-SA/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# توسيع التطبيق الخاص بك + +لقد أكملنا بالفعل جميع الخطوات المختلفة اللازمة لإنشاء موقعنا على الويب: + +حان الوقت للتدريب! + +أول شيء نحتاجه في مدونتنا هو، على الأرجح، صفحة لعرض مشاركة واحدة، أليس كذلك؟ + +لدينا بالفعل نموذج `Post` ، لذلك لا نحتاج إلى إضافة أي شيء إلى `models.py`. + +## إنشاء رابط نموذج لتفاصيل المشاركة + +سنبدأ بإضافة رابط داخل ملف `blog/templates/blog/post_list.html` افتحه في محرر التعليمات البرمجية، وحتى الآن يجب أن يبدوا هكذا: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %} نريد الحصول على رابط من عنوان المشاركة في قائمة المشاركات إلى صفحة تفاصيل المشاركة. دعونا نغير `

{{ post.title }}

` بحيث يربط صفحة تفاصيل المشاركة:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %} حان الوقت لشرح `{% url 'post_detail' pk=post.pk %}`. كما قد تظن، فإن علامات `{% %}` تعني أننا نستخدم علامات قالب جانغو. هذه المرة سوف نستخدم واحدة منهم والتي ستقوم بإنشاء عنوان URL لنا!{% endraw %} + +الجزء `post_detail` يعني أن جانغو سوف يتوقع عنوان URL في `blog/urls.py` مع name=post_detail. + +وماذا عن `pk=post.pk`؟ `pk` هو اختصار للمفتاح الأساسي، وهو اسم فريد لكل سجل في قاعدة البيانات. كل نموذج جانغو لديه حقل يعمل كمفتاح رئيسي له، وأياً كان اسمه الآخر، فإنه يمكن أن يشار إليه أيضاً باسم "pk". ونظرا لأننا لم نحدد مفتاحا أساسيا في نموذج `Post`، فإن جانغو ينشئ واحدا لنا (بشكل افتراضي، هو حقل يسمى "id" يحتوي على رقم يزيد لكل سجل، أي 1 و 2 و 3) ويضيفه كحقل لكل واحدة من مشاركاتنا. نصل إلى المفتاح الأساسي من خلال كتابة `post.pk`، بنفس الطريقة التي نصل بها إلى الحقول الأخرى (`title`, `author`, etc.) في الكائن `Post`! + +الآن عندما ننتقل إلى http://127.0.0.1:8000/ سيكون لدينا خطأ (كما هو متوقع، نظرا لأنه لا يوجد لدينا عنوان URL أو *view* ل `post_detail`). وسوف تبدو كما يلي: + +![خطأ NoReverseMatch](images/no_reverse_match2.png) + +## إنشاء عنوان URL لتفاصيل المشاركة + +لنقم بإنشاء عنوان URL في `urls.py` من أجل `post_detail` *view* الخاص بنا! + +نريد عرض تفاصيل مشاركتنا الأولى في هذا الرابط ****: http://127.0.0.1:8000/post/1/ + +دعونا ننشئ عنوان URL في ملف `blog/urls.py` لتوجيه جانغو إلى *view* باسم `post_detail`، الذي سوف يعرض مشاركة بأكملها. افتح ملف `blog/urls.py` في محرر التعليمات البرمجية، وأضف السطر `path('post//', views.post_detail, name='post_detail'),` بحيث يبدو الملف كهذا: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +يحدد هذا الجزء `post//` نمط عنوان URL - وسوف نشرحه لك: + +- `post/` يعني أن عنوان URL يجب أن يبدأ بكلمة **post** يتبعه **/**. حتى الآن كل شيء جيد. +- `` - هذا الجزء أكثر صعوبة. وهو يعني أن جانغو يتوقع قيمة صحيحة وسيقوم بتحويلها إلى عرض كمتغير يسمى `pk`. +- `/` - ثم نحتاج إلى **/** مرة أخرى قبل الانتهاء من عنوان URL. + +هذا يعني إذا قمت بإدخال `http://127.0.0.1:8000/post/5/` في المتصفح، جانغو سيفهم أنك تبحث عن *view* يسمى `post_detail` وسينقل معلومة أن `pk` تساوي `5` إلى ذلك الـ *view*. + +حسنا، لقد أضفنا نمط عنوان URL جديد إلى `blog/urls.py`! دعونا نقم بتحديث الصفحة http://127.0.0.1:8000/ بوم! توقف الخادم عن العمل مرة أخرى. ألقي نظرة على وحدة التحكم – كما هو متوقع، هناك خطأ آخر! + +![AttributeError](images/attribute_error2.png) + +هل تذكر ما الخطوة التالية؟ إنها إضافة طريقة عرض! + +## إضافة مشاركة لعرض التفاصيل + +هذه المرة *view* الخاص بنا يُعطى معلمة إضافية، `pk`. الـ *view* الخاص بنا يحتاج إلى الإمساك به، أليس كذلك؟ لذلك سنقوم بتعريف وظيفتنا كـ `def post_detail(request, pk):`. لاحظ أن هذا العامل يجب أن يكون له نفس الاسم بالضبط الذي حددناه في `urls` (`pk`). لاحظ أيضا أن حذف هذا المتغير غير صحيح وسوف يؤدي إلى خطأ! + +الآن، نريد أن نحصل على مشاركة مدونة واحدة فقط. للقيام بذلك، يمكننا استخدام مجموعات الاستعلامات، مثل هذا: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk)Post.objects.get(pk=pk) +``` + +ولكن توجد مشكلة في التعليمات البرمجية هذه. إذا لم يكن هناك `Post` مع الـ `primary key` (`pk`) المُعطى سيكون لدينا خطأ قبيح جداً! + +![خطأ DoesNotExist](images/does_not_exist2.png) + +نحن لا نريد ذلك! لكن لحسن الحظ جانغو يأتي مع شيء سوف يتعامل مع ذلك لنا: `get_object_or_404`. في حالة عدم وجود `Post` مع `pk` المعطى، سيتم عرض صفحة أفضل بكثير، صفحة `Page Not Found 404`. + +![لم يتم العثور على الصفحة](images/404_2.png) + +الخبر الجيد هو أنه يمكنك في الواقع إنشاء صفحة `Page not found` الخاصة بك وجعلها جميلة كما تريد. لكنها ليست مهمة جداً الآن، لذلك سنتخطى ذلك. + +طيب، حان الوقت لإضافة *view* لملف `views.py` لدينا! + +في `blog/urls.py` قمنا بإنشاء قاعدة عنوان URL اسمها `post_detail` التي تشير إلى طريقة عرض تسمى `views.post_detail`. وهذا يعني أن جانغو سوف يتوقع وظيفة عرض تسمى `post_detail` داخل `blog/views.py`. + +يجب علينا فتح `blog/views.py` في محرر التعليمات البرمجية وإضافة التعليمات البرمجية التالية بالقرب من أسطر `from` الأخرى: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +وفي نهاية الملف سوف نقوم بإضافة *view*: + +{% filename %}blog/views.py{% endfilename %} + +```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/ + +![عرض قائمة المشاركات](images/post_list2.png) + +لقد نجحت! ولكن ماذا يحدث عند النقر على رابط في عنوان مشاركة المدونة؟ + +![خطأ TemplateDoesNotExist](images/template_does_not_exist2.png) + +أوه لا! خطأ آخر! لكننا نعرف بالفعل كيفية التعامل معه، أليس كذلك؟ نحن بحاجة إلى إضافة قالب! + +## إنشاء قالب لتفاصيل المشاركة + +سنقوم بإنشاء ملف في `blog/templates/blog` يسمى `post_detail.html` وفتحه في محرر التعليمات البرمجية. + +أدخل الأمر التالي: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +مرة أخرى نحن نوسع `base.html`. في الكتلة `content` نريد عرض تاريخ نشر المشاركة (إذا كان موجودا) والعنوان والنص. لكن علينا أن نناقش بعض الأشياء الهامة، أليس كذلك؟ + +{% raw %}`{% if ... %} ... {% endif %}` علامة قالب يمكننا استخدامها عندما نريد التحقق من شيء. (تذكر `if ... else ...` من فصل **Introduction to Python**؟) في هذا السيناريو نريد أن نتحقق إذا كان الـ `published_date` الخاص بالمشاركة ليس خالياً. {% endraw %} + +حسنًا، يمكننا تحديث صفحتنا ومعرفة ما إذا كانت `TemplateDoesNotExist` قد ذهبت الآن. + +![صفحة تفاصيل المشاركة](images/post_detail2.png) + +ياي! إنه يعمل! + +# وقت النشر! + +سيكون من الجيد معرفة ما إذا كان موقع الويب الخاص بك لا يزال يعمل على PythonAnywhere، أليس كذلك؟ دعونا نحاول النشر مرة أخرى. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ 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](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(تذكر أن تستبدل `` بالمجال الفرعي لـ PythonAnywhere الفعلي، بدون أقواس الزاوية. ) + +## تحديث الملفات الثابتة على الخادم + +الخوادم مثل PythonAnywhere تحب معاملة "الملفات الثابتة" (مثل ملفات CSS) بشكل مختلف عن ملفات بايثون لأنها يمكن أن تحسن تحميلها بشكل أسرع. ونتيجة لذلك، كلما قمنا بتغيير ملفات CSS الخاصة بنا، نحن بحاجة إلى تشغيل أمر إضافي على الخادم لإخباره بتحديثهم. الأمر يسمى `collectstatic`. + +ابدأ بتفعيل الـ virtualenv الخاص بك إذا لم يكن يزال نشطا من قبل (PythonAnywhere يستخدم أمر يسمى `workon` للقيام بذلك. إنه تماما مثل أمر `source myenv/bin/activate` الذي تستخدمه على جهاز الكمبيوتر الخاص بك: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +الأمر `manage.py collectstatic` يشبه قليلاً `manage.py migrate`. نحن نقوم ببعض التغييرات على تعليماتنا، ومن ثم نقول لجانغو *apply* لهذه التغييرات، إما إلى مجموعة الملفات الثابتة للخادم، أو إلى قاعدة البيانات. + +وعلى أية حال، نحن الآن مستعدون للانتقال إلى ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (من زر القائمة في الجزء العلوي الأيمن من وحدة التحكم) و الضغط على **Reload**، ثم انظر إلى صفحة https://subdomain.pythonanywhere.com لرؤية النتيجة. + +هذا ينبغي ان يكون كل شيء! مبروك:) \ No newline at end of file diff --git a/ar-SA/how_the_internet_works/README.md b/ar-SA/how_the_internet_works/README.md new file mode 100644 index 00000000000..8e8c8b490d3 --- /dev/null +++ b/ar-SA/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# كيف يعمل الإنترنت + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc). +> +> هذا الفصل مستوحى من حديث "كيف تعمل شبكة الإنترنت" جيسيكا مك كيلار (http://web.mit.edu/jesstess/www/). + +نحن نراهن انك تستخدم الأنترنت كل يوم. ولكن هل تعرف فعلا ما يحدث عند كتابة عنوان مثل https://djangogirls.org في متصفحك والضغط على `enter`؟ + +أول شيء تحتاج إلى فهمه هو أن الموقع يتكون من مجموعة من الملفات المحفوظة على قرص صلب، تماما مثل أفلامك، الموسيقى، أو الصور. ومع ذلك، هناك جزء واحد فريد للمواقع: وهي تعليمات كمبيوتر برمجية تسمى HTML. + +إذا كنت لا تعرف البرمجة فإنه سيكون من الصعب فهم HTML في البداية، ولكن متصفحات الويب الخاص بك (مثل كروم، سفاري، فايرفوكس، الخ) تحبها. تم تصميم متصفحات الويب لفهم هذا الكود، اتباع التعليمات الخاصة به، وتقديم هذه الملفات التي تشكل موقع الويب الخاص بك، بالطريقة التي تريدها. + +كما هو الحال مع كل ملف، نحن بحاجة إلى تخزين ملفات HTML في مكان ما على قرص الثابت. بالنسبة إلى الإنترنت، نستخدم أجهزة كمبيوتر خاصة وقوية تسمى *خوادم*. أنهم لا يملكون شاشة أو ماوس أو لوحة مفاتيح، لأن الغرض الرئيسي منها هو لتخزين البيانات وخدمتها. لذالك يسمون *servers* لأنهم *serve* خدم ينقلون بياناتك. + +حسنا! لكنك تريد ان ترى كيف تعمل الأنترنت أليس كذالك؟ + +لقد رسمنا لك صورة ، ستبدو هكذا: + +![الرقم 1.1](images/internet_1.png) + +تبدو كفوضى ، اليس كذالك؟ في الواقع هي شبكة أجهزة متصلة (*ملقمات* المشار إليها أعلاه). مئات الآلاف من آلات! كيلومترات عديدة من الكابلات حول العالم! يمكنك زيارة موقع "خريطة غواصات الكابلات" (http://submarinecablemap.com) لمعرفة مدى تعقيد الشبكة. هنا لقطة شاشة من الموقع: + +![الرقم 1.2](images/internet_3.png) + +أنها رائعة، أليس كذلك؟ ولكن ليس من الممكن أن يكون هناك سلك بين كل آلة متصلة بالإنترنت. إذا ، للوصول إلى جهاز (على سبيل المثال، حيث يتم حفظ https://djangogirls.org) نحن بحاجة لتمرير طلب من خلال آلات مختلفة كثيرة. + +ستبدو كالشكل التالي: + +![الرقم 1.3](images/internet_2.png) + +تخيل عند كتابة https://djangogirls.org، يمكنك إرسال رسالة تقول: "عزيزي جانغو الفتيات، أريد أن أرى الموقع djangogirls.org. أرسله لي، رجاء! " + +رسالتك تذهب إلى مكتب البريد الأقرب إليك. ثم تذهب إلى آخر أقرب قليلا إلى المرسل إليه، ثم إلى آخر، وآخر حتى يتم تسليمها إلى وجهتها. الشيء الفريد هنا إذا قمت بإرسال العديد من الرسائل (*حزم البيانات*) إلى نفس المكان، يمكن أن تذهب من خلال مكاتب بريد مختلفة تماما (*أجهزة التوجيه*). وهذا يعتمد على كيفية التوزيع في كل مكتب. + +![الرقم 1.4](images/internet_4.png) + +هذه هي الطريقة التي تعمل بها - ترسل رسائل وتتوقع بعض الاستجابة. بدلاً من الورق والقلم يمكنك استخدام وحدات البايت من البيانات، ولكن الفكرة هي نفسها! + +بدلاً من عناوين مع اسم الشارع، والمدينة، والرمز البريدي واسم البلد، نحن نستخدم عناوين IP. يسأل الكمبيوتر أولاً DNS (نظام اسم المجال) لترجمة djangogirls.org إلى عنوان IP. وهي تعمل قليلا مثل كتب الهاتف القديمة حيث يمكنك البحث عن اسم الشخص الذي تريد الاتصال به والعثور على رقم الهاتف وعنوانه. + +عندما تقوم بإرسال رسالة، فإنها تحتاج إلى بعض الميزات لتسليمها بشكل صحيح: عنوان، ختم، إلخ. انت ايضا تستخدم لغة يفهمها المتلقي، اليس كذالك؟ وينطبق نفس الشيء على *حزم البيانات* انت ترسل لترى موقع انترنت. نحن نستخدم بروتوكول يسمى HTTP (بروتوكول نقل النص التشعبي). + +لذلك، أساسا، عندما يكون لديك موقع على شبكة الإنترنت، تحتاج إلى يكون لديك *ملقم* (آلة) حيث يعيش. عندما يستلم *الملقم* *طلب* وارد (في رسالة)، يرسل إلى موقع الويب الخاص بك (في رسالة أخرى). + +بما ان هذا برنامج تعليمي لدجانغو ، قد تسأل ماذا يفعل دجانغو. عندما تقوم بإرسال استجابة، لا تريد دائماً إرسال نفس الشيء للجميع. من الأفضل بكثير ان تكون احرفك مشخصة، وخاصة للشخص الذي كتب للتو لك، أليس كذلك؟ جانغو يساعدك في إنشاء هذه الرسائل الشخصية، والمثيرة للاهتمام. :) + +يكفي الحديث--وقت البناء! \ No newline at end of file diff --git a/ar-SA/html/README.md b/ar-SA/html/README.md new file mode 100644 index 00000000000..f88f9dd1c2c --- /dev/null +++ b/ar-SA/html/README.md @@ -0,0 +1,227 @@ +# مقدمة إلى HTML + +قد تسأل ما هو القالب؟ + +القالب هو ملف يمكننا إعادة استخدامه لتقديم معلومات مختلفة بتنسيق ثابت - على سبيل المثال، يمكنك استخدام قالب لمساعدتك على كتابة رسالة، على الرغم من أن كل رسالة قد تحتوي على مضمون مختلف ويتم توجيهها إلى شخص مختلف ، باستعمال القالب ستظهر بفس الشكل. + +تم وصف تنسيق قالب جانغو في لغة تسمى HTML (وهذا هو ال HTML التي ذكرناها في الفصل الأول،**How the Internet works**). + +## ما هي HTML؟ + +HTML هو رمز يتم تفسيره بواسطة متصفح الويب - مثل كروم أو فايرفوكس أو سفاري - لعرض صفحة ويب للمستخدم. + +نقصد ب HTML "HyperText Markup Language". **HyperText** هو نص يعتمد على الإرتباطات التشعبية بين الصفحات. **Markup** يعني أننا اتخذنا وثيقة ووضعنا علامة عليها مع رمز لنقول ل (في هذه الحالة، متصفح) كيفية تفسير الصفحة. تم إنشاء شفرة HTML باستخدام علامات **tags**، حيث يبدأ كل منها باستخدام `<` وينتهي ب `>`. تمثل هذه العلامات علامات **elements**. + +## قالبك الأول! + +إنشاء قالب يعني إنشاء ملف قالب. كل شيء هو ملف، هو؟ ربما كنت قد لاحظت هذا بالفعل. + +يتم حفظ قوالب في `blog/templates/blog` الدليل. لذا أولاً أنشئ دليل يسمى `templates` داخل دليل المدونة الخاص بك. قم بإنشاء دليل آخر يسمى `blog` داخل دليل القوالب الخاصة بك: + + blog + └───templates + └───blog + + +(قد تتساءل لماذا نحتاج إلى دليلي `blog` - كما سوف تكتشف في وقت لاحق، وهذا هو مجرد تسمية اصطلاح مفيدة تجعل الحياة أسهل عندما تبدأ الأمور أكثر تعقيدا) + +والآن قم بإنشاء ملف `post_list.html` (فقط اتركه فارغاً للآن) داخل دليل `blog/templates/blog`. + +انظر كيف يبدو موقع الويب الخاص بك الآن: http://127.0.0.1:8000/ + +> إذا كان لا يزال لديك خطأ `TemplateDoesNotExist`,، حاول إعادة تشغيل الخادم الخاص بك. انتقل الى سطر الأوامر حاول ايقاف الخادم (بالضغط على Ctrl+C - مفتاح التحكم و C معا) وإعادة تشغيله من خلال الأمر ` python manage.py runserver `. + +![الرقم 11.1](images/step1.png) + +لم يعد هناك خطأ! تهانينا! :) ومع ذلك، لا يقوم موقعك بنشر أي شيء إلا صفحة فارغة، لأن قالبك فارغ أيضا. نحن بحاجة إلى إصلاح ذلك. + +افتح الملف الجديد في محرر التعليمات البرمجية، وأضف ما يلي: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +كيف يبدو موقعك الآن؟ يرجى زيارة الموقع لمعرفة ذالك: http://127.0.0.1:8000/ + +![الرقم 11.2](images/step3.png) + +لقد نجحت. عمل جيد هناك! :) + +* السطر `` ليس علامة HTML. هي تعلن فقط نوع المستند. هنا، إنها تبلغ المتصفح بأن نوع المستند هو [HTML5](https://html.spec.whatwg.org/#the-doctype). هذا هو دائما بداية أي ملف HTML5. +* إن العلامة الأساسية، ``، هي دائما بداية أي صفحة ويب و `` هي دائما النهاية. كما ترون، المحتوى الكامل للموقع يقع بين علامة البداية `` وعلامة الإغلاق `` +* `

`علامة لعناصر الفقرة؛ `

` يغلق كل فقرة + +## الرأس والجسم + +كل صفحة HTML تنقسم إلى عنصرين هما **head** و **body**. + +* **head** هو عنصر يحتوي على معلومات حول المستند الذي لا يتم عرضه على الشاشة. + +* **body** هو عنصر يحتوي على كل شيء يتم عرضه كجزء من صفحة ويب. + +نحن نستخدم `` لإخبار المتصفح عن إعدادات الصفحة، و `` ليقول ما هو موجود فعلا في الصفحة. + +على سبيل المثال، يمكنك وضع عنصر عنوان صفحة ويب داخل ``، مثل هذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +قم بحفظ الملف وقم بتحديث الصفحة الخاصة بك. + +![الرقم 11.3](images/step4.png) + +لاحظ كيف أن المستعرض قد فهم أن "Ola's blog" هو عنوان الصفحة الخاصة بك؟ لقد فسرت `Ola's blog` ووضعت النص في شريط عنوان المتصفح (سيتم استخدامه أيضا للإشارات المرجعية وما إلى ذلك). + +ربما كنت قد لاحظت أيضا أن كل علامة افتتاح تقابلها *closing tag* مع `/` وذالك العنصر هو *nested* (بمعنى أنه لا يمكنك إغلاق علامة معينة حتى يتم إغلاق كل العلامات الموجودة داخلها). + +أنها مثل وضع الأمور في صناديق. لديك صندوق واحد كبيرة ، ``؛ يوجد داخله ``، والذي يحتوي على صناديق صغيرة `

`. + +تحتاج إلى اتباع قواعد *الإغلاق* هذه ، و *تداخل* العناصر – إذا لم تقم بذالك، المستعرض قد لا يكون قادراً على تفسيرها بشكل صحيح وسيتم عرض الصفحة الخاصة بك بشكل غير صحيح. + +## تخصيص القالب الخاص بك + +يمكنك الآن الحصول الأن على بعض المتعة ومحاولة تخصيص القالب الخاص بك! وإليك بعض العلامات المفيدة لذلك: + +* `

A heading

` لأهم عنوان لديك +* `

A sub-heading

` لعنوان في المستوى التالي +* `

A sub-sub-heading

` ومع ذالك إلى `
` +* `

فقرة من النص

` +* ويؤكد `text` على النص الخاص بك +* ويؤكد `text` بشدة على النص الخاص بك +* `
`يذهب إلى سطر آخر (لا يمكنك وضع أي شيء داخل br وليس هناك أي علامة إغلاق) +* `link` إنشاء رابط +* `
  • first item
  • second item
` أنشئ قائمة مثل هذه! +* `
` تعرف جزء من الصفحة +* `` يحدد مجموعة من روابط التنقل +* `
` يحدد محتوى مستقل ومحتفظ بذاته +* `
` يحدد القسم في مستند +* `
` يحدد رأس المستند أو القسم +* `
` يحدد المحتوى الرئيسي للمستند +* `` يحدد بعض المحتوى بعيداً عن المحتوى الذي يتم وضعه فيه (مثل الشريط الجانبي) +* `
` يحدد تذييل المستند أو المقطع +* `` يحدد الوقت المحدد (أو التاريخ والوقت) + +هنا مثال لقالب كامل انسخه والصقه `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +لقد قمنا بإنشاء قسم `header` واحد وقسمان `article` اثنان هنا. + +* يحتوي العنصر `header` على عنوان مدونتنا - إنه عنوان ورابط +* العنصران `article` يحتويان مشاركات مدونتنا مع تاريخ نشر في عنصر `time`، عنصر `h2` مع عنوان مشاركة قابل للنقر وعنصر (فقرة) `p` لنص مشاركة المدونة الخاص بنا. + +هو يتيح لنا هذا التأثير: + +![الرقم 11.4](images/step6.png) + +يااي! ولكن حتى الآن، يعرض نموذجنا تماما **نفس المعلومات** - بينما كنا نتحدث عن النماذج في وقت سابق للسماح لنا بعرض معلومات ** مختلفة ** في **نفس التنسيق**. + +ما كنا نريد فعله حقا هو اضهار مشاركات حقيقية في ادارة دجانغو ، وذالك اين سنذهب لاحقا ،. + +## شيء اخر: أنشر الوقت! + +سيكون من الجيد أن نرى كل هذا على الإنترنت، ايس كذالك؟ دعونا ننشر بايثون في كل مكان اخر: + +### فوض وادفع التعليمات البرمجية الخاصة بك الى Github + +أولاً، دعونا نرى ما هي الملفات التي تغيرت منذ آخر نشر (شغل هذه الأوامر محليا ، ليس في بايثون في كل مكان): + +{% filename %}command-line{% endfilename %} + + $ git status + + +تأكد من أنك في مجلد `djangogirls` ودعنا نخبر `git` بتضمين جميع التغييرات ضمن هذا المجلد: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +قبل رفع جميع الملفات دعنا نرى ماذا سترفع `git` ( جميع الملفات التي ترفعها `git` يجب ان تضهر باللون الأخضر): + +{% filename %}command-line{% endfilename %} + + $ git status + + +شارفنا على الانتهاء ، الآن حان الوقت لنقول لها ان تحفض هذه التغييرات بتاريخها. سنعطيه "رسالة التزام" حيث نصف ما قمنا بتغييره. يمكنك كتابة ما تريد في هذه الحالة ، لكن من الأفضل ان تكتب شيء يدل على ما قمت بفعله حتى تتذكر في المستقبل. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "Changed the HTML for the site." + + +> **ملاحظة** تأكد من استخدام علامات الاقتباس المزدوجة حول رسالة التفويض. + +عندما نقوم بذالك نرفع او ندفع بتعديلاتنا إلى GitHub: + +{% filename %}command-line{% endfilename %} + + $ git push + + +### اسحب التعليمات الجديدة إلى PythonAnywhere، وأعد تحميل تطبيق الويب + +* افتح [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) واذهب الى **Bash console** او افتح واحدة جديدة وشغل هذا الأمر: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +ستحتاج إلى استبدال `` باسم النطاق الفرعي الخاص بك PythonAnywhere بدون أقواس الزاوية. اسم المجال الفرعي الخاص بك عادة هو اسم المستخدم PythonAnywhere الخاص بك، ولكن في بعض الحالات قد يكون مختلفا بعض الشيء (مثل إذا كان اسم المستخدم الخاص بك يحتوي على أحرف كبرى). إذا كان هذا الأمر لا يعمل، استخدم أمر `ls` (قائمة الملفات) للعثور على النطاق الفرعي/المجلد الفعلي الخاص بك، ثم `cd` إلى هناك. + +الآن شاهد التعليمات البرمجية الخاصة بك يتم تنزيلها. إذا كنت ترغب في التحقق من أنه وصل، يمكنك الانتقال إلى صفحة **"الملفات"** وعرض التعليمات البرمجية الخاصة بك على PythonAnywhere (يمكنك الوصول إلى صفحات بايثون في كل مكان الأخرى من زر القائمة على صفحة وحدة التحكم). + +* وأخيراً، انتقل إلى ["Web" page](https://www.pythonanywhere.com/web_app_setup/) واضغط على **Reload** في تطبيق الويب الخاص بك. + +تحديثك يجب ان يكون متاح, قم بعمل تحديث صفحة الموقع في المتصفح. التغييرات يجب ان تظهر لك الان \ No newline at end of file diff --git a/ar-SA/installation/README.md b/ar-SA/installation/README.md new file mode 100644 index 00000000000..f1a3aff5161 --- /dev/null +++ b/ar-SA/installation/README.md @@ -0,0 +1,68 @@ +# إذا كنتم تتبعون الدليل التطبيقي من منازلكم + +إذا كنتم تتبعون الدليل التطبيقي من منازلكم وليس في أحد [فعاليات Django Girls](https://djangogirls.org/events/)، يمكنك تخطي هذا الفصل الآن والانتقال مباشرة إلى فصل ["كيف يعمل الإنترنت" ](../how_the_internet_works/README.md). + +وذلك لأننا سنغطي جزئية تحميل بعض البرامج التي نحتاجونها في الدليل التطبيقي - هذه مجرد صفحة إضافية تجمع جميع التعليمات لتحميل البرامج في صفحة واحدة (ستكون مفيدة لبعض ورش العمل). تستطيعون اختيار تحميل جميع البرامج في هذه الصفحة من الآن إن أردتم. لكن إذا أردنم البدء في التعلم قبل تحميل البرامج اللازمة على أجهزتكم، فيمكنكم تجاهل هذا الفصل وسنشرح لك جزئية التحميل لاحقاً كلما احتجناها. + +بالتوفيق! + +# إذا كنتم حاضرين لورشة العمل + +إذا كنتم حاضرين لأحد [فعاليات Django Girls](https://djangogirls.org/events/): + +* ورشة العمل قد تبدأ بـ "حفلة التحميل" قبل الورشة الأساسية. إذا كنتم في حقلة التحميل، فهذه الصفحة لكم! اتبعوا التعليمات هنا لتحصلوا على كل ما تحتاجونه للورشة، بمساعدة المرشدات إذا احتجتم. ثم في الورشة الأساسية، يمكنكم تجاهل جزئية التحميل التي ستمر بكم أثناء قرائتكم للدليل التطبيقي. +* قد يكون منظموا الورشة طلبوا منكم تحميل كل شيء على أجهزتكم من منازلكم قبل بدء الورشة. إذا كان طلب منكم هذا، فهذه الصفحة لكم! اتبعوا التعليمات هنا، بأفضل قدرنكم. ثم في الورشة الأساسية، عندما تصلون لخطوة تحميل في الدليل التطبيقي، إذا لم تستطعون تحميل المطلوب فيمكنكم طلب المساعدة من المرشدات. +* إذا لم تبدأ ورشة العمل بحفلة التثبيت (أو لم تستطيعوا الحضور)، ولم يطلبوا منكم المنظمين تحميل المتطلبات قبل الحضور، تجاهلوا هذه الصفحة واذهبوا مباشرة إلى فصل [كيف يعمل الانترنت](../how_the_internet_works/README.md). ستحملون جميع ما تحتاجونه خلال اتباعكم للدليل التطبيقي. + +# التحميل + +في هذا الدليل التطبيقي ستبنون مدونة. ولعمل ذلك، أثناء تتبعكم للدليل التطبيقي ستمرون بتعليمات لتحميل برامج مختلفة على أجهزتكم وإعداد بعض الحسابات على الإنترنت كلما تطلب ذلك. هذه الصفحة تجمع جميع التعليمات لتحميل البرامج وتسجيل الحسابات في مكان واحد (ستكون مفيدة لبعض ورش العمل) + + {% include "/chromebook_setup/instructions.md" %} + + + +# مقدمة مختصرة عن موجه الأوامر {#command-line} + +العديد من الخطوات أدناه تشير إلى "وحدة التحكم"، "الطرف"، "نافذة الأوامر"، أو "سطر الأوامر" -- هذه كلها تعني نفس الشيء: نافذة على جهاز الكمبيوتر الخاص بك حيث يمكنك إدخال الأوامر. عندما تصل إلى البرنامج التعليمي الرئيسي، سوف تتعلم المزيد عن سطر الأوامر. الآن، الشيء الرئيسي الذي تحتاج إلى معرفته هو كيفية فتح نافذة أمر وكيف تبدو: {% include "/intro_to_command_line/open_instructions.md" %} + +# تثبيت بايثون {#python} + +{% include "/python_installation/instructions.md" %} + +# تثبيت محرر التعليمات البرمجية {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# إعداد virtualenv وتثبيت Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# تثبيت Git {#git} + +{% include "/deploy/install_git.md" %} + +# إنشاء حساب Github {#github-account} + +انتقل إلى [GitHub.com](https://www.github.com) وقم بالتسجيل للحصول على حساب مستخدم مجاني جديد. تأكد من تذكر كلمة المرور الخاصة بك (أضفها إلى مدير كلمات المرور الخاصة بك، إذا كنت تستخدم أحدهم). + +# قم بإنشاء حساب بايثون في كل مكان {#pythonanywhere-account} + +{% include "/deploy/signup_pythonanywhere.md" %} + +# ابدأ بالقراءة + +تهانينا، انت جاهز الأن وعلى استعداد للإنطلاق! إذا كان لا يزال لديك بعض الوقت قبل انعقاد حلقة العمل، سيكون من المفيد بدء قراءة عدد قليل من فصول البداية: + +* [كيف يعمل الإنترنت](../how_the_internet_works/README.md) + +* [مقدمة لسطر الأوامر](../intro_to_command_line/README.md) + +* [مقدمة إلى بايثون](../python_introduction/README.md) + +* [ما هو جانغو؟](../django/README.md) + +# استمتع بورشة العمل! + +عند بدء ورشة العمل، ستتمكن من الانتقال مباشرة إلى [أول مشروع جانغو الخاص بك!](../django_start_project/README.md) لأنك قمت بالفعل بتغطية المادة في الفصول السابقة. \ No newline at end of file diff --git a/ar-SA/intro_to_command_line/README.md b/ar-SA/intro_to_command_line/README.md new file mode 100644 index 00000000000..026f8f30e70 --- /dev/null +++ b/ar-SA/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# مقدمة لواجهة سطر الأوامر + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [Your new friend: Command Line](https://www.youtube.com/watch?v=jvZLWhkzX-8). + +أنه مثير، أليس كذلك؟! عليك كتابة السطر الأول الخاص بك من التعليمات البرمجية في بضع دقائق فقط! :) + +**دعونا نقدم لكم صديقكم الأول: سطر الأوامر!** + +الخطوات التالية سوف تظهر لك كيفية استخدام النافدة السوداء التي يستخدمها جميع الهكر. قد تبدو مخيفه قليلاً في البداية ولكن حقاً أنها مجرد موجه تنتظر الأوامر منك. + +> **ملاحظة** يرجى ملاحظة أن طوال هذا الكتاب يمكننا استخدام عبارات 'الدليل' و 'مجلد' بالتبادل ولكنها واحدة ونفس الشيء. + +## ما هو سطر الأوامر؟ + +النافذة، والتي عادة ما تسمى **سطر الأوامر** أو **واجهة سطر الأوامر**، هو تطبيق يستند إلى النص للعرض، والمناولة، ومعالجة الملفات الموجودة على جهاز الكمبيوتر الخاص بك. أنه يشبه إلى حد كبير ويندوز إكسبلورر أو الباحث في Mac، ولكن دون واجهة رسومية. أسماء أخرى لسطر الأوامر هي: *cmd*, *CLI*, *prompt*, *console* أو *terminal*. + +## إفتح واجهة سطر الأوامر + +لبدء بعض التجارب نحن بحاجة إلى فتح واجهة سطر الأوامر لدينا أولاً. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## موجه + +يجب أن تشاهد الآن نافذة بيضاء أو سوداء تنتظر الأوامر الخاصه بك. + + + +إذا كنت على Mac أو Linux، ربما ترى `$`، مثل هذا: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +على Windows، ربما ترى `>`، مثل هذا: + +{% filename %}command-line{% endfilename %} + + > + + +ألقي نظرة على قسم لينكس أعلاه مباشرة -- سترى شيئا مثل هذا عندما تصل إلى PythonAnywhere لاحقا في البرنامج التعليمي. + + + +سيتم إرفاق كل أمر مسبقاً بواسطة `$` أو `>` ومسافة واحدة، ولكن يجب ألا تكتبها. الكمبيوتر الخاص بك سوف يفعله من أجلك. :) + +> ملاحظة صغيرة: في حالتك قد يكون هناك شيء مثل `C:\Users\ola>` أو `Olas-MacBook-Air:~ ola$` قبل علامة الطلب، وهذا هو 100% على ما يرام. + +الجزء الذي يصل إلى ويحتوي على `$` أو `>` يسمى *موجه سطر الأوامر*، أو *الموجه* بإختصار. إنه يطالبك بإدخال شيء هناك. + +في البرنامج التعليمي، عندما نريد منك كتابة أمر ما، سنقوم بتضمين `$` أو `>`، وأحيانا أكثر إلى اليسار. تجاهل الجزء الأيسر واكتب فقط في الأمر، الذي يبدأ بعد الموجه. + +## الأمر الأول الخاص بك (ياي!) + +دعونا نبدأ بكتابة هذا الأمر: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +ثم اضغط على `enter`. هذه هي النتيجة لدينا: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +كما ترون، الكمبيوتر قد طبع اسم المستخدم الخاص بك. أنيق، هاه؟ :) + +> حاول كتابة كل أمر؛ لا تنسخ وتلصق. سوف تتذكر أكثر بهذه الطريقة! + +## الأساسيات + +كل نظام تشغيل يحتوي على مجموعة مختلفة قليلاً من أوامر سطر الأوامر، لذا تأكد من اتباع التعليمات لنظام التشغيل الخاص بك. دعونا نحاول هذا،هيا بنا؟ + +### الدليل الحالي + +سيكون من الجميل أن نعرف أين نحن الآن، اليس كذالك؟ لنرى. اكتب هذا الأمر وإضغط `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> ملاحظة: 'pwd' تعني 'طباعة دليل العمل'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> ملاحظة: 'cd' تعني 'تغيير الدليل'. مع PowerShell يمكنك استخدام pwd تماما مثل Linux أو Mac OS X. + + + +ربما سترى شيئا مشابها على الجهاز الخاص بك. عندما تقوم بفتح سطر الأوامر تبدأ عادة في الدليل الرئيسي للمستخدم الخاص بك. + +* * * + +### معرفة المزيد حول الأمر + +العديد من الأوامر التي يمكنك كتابتها في موجه الأوامر لها مساعدة مدمجة يمكنك عرضها وقراءتها! على سبيل المثال، لمعرفة المزيد عن أمر الدليل الحالي: + + + +OS X و Linux لديهما أمر `man` الذي يعطيك المساعدة في الأوامر. جرب `man pwd` وشاهد ما يقوله، أو ضع `man` قبل أوامر أخرى لمشاهدة مساعدتهم. ناتج `man` هو عادة صفحة استخدم زر المسافة للإنتقال إلى الصفحة التالية، و `q` للخروج من النظر إلى المساعدة. + + + + + +إضافة `/?` لاحقة لمعظم الأوامر سوف يطبع صفحة المساعدة. قد تحتاج إلى تمرير نافذة الأوامر الخاصة بك لرؤية كل شيء. جرب `cd /?`. + + + +### قائمة الملفات والدلائل + +اذاً ماذا فيها؟ سيكون من الرائع معرفة ذلك، دعونا نرى: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> ملاحظة: في PowerShell يمكنك أيضا استخدام 'ls' مثل Linux و Mac OS X. + +* * * + +### تغيير الدليل الحالي + +الآن، دعونا نذهب إلى دليل سطح المكتب لدينا: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +لاحظ أن اسم الدليل "سطح المكتب" قد يترجم إلى لغة حساب لينكس الخاص بك. إذا كان الأمر كذلك، ستحتاج إلى استبدال `Desktop` بالاسم المترجم؛ على سبيل المثال، `Schreibtisch` بالألمانية. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +تحقق إذا كان تم تغييره حقا: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +ها هي! + +> نصيحة المحترفين: إذا كتبت `cd D` ثم ضغطت على `tab` في لوحة المفاتيح، فسيملأ سطر الأوامر تلقائيا بقية الاسم حتى تتمكن من التنقل بشكل أسرع. إذا كان هناك أكثر من مجلد واحد يبدأ بـ "D"، اضغط على مفتاح `tab` مرتين للحصول على قائمة الخيارات. + +* * * + +### إنشاء دليل + +ماذا عن إنشاء دليل تدريب على سطح المكتب الخاص بك؟ يمكنك القيام بذلك بهذه الطريقة: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% filename %}command-line{% endfilename %} + + > mkdir practice + + + + +سيؤدي هذا الأمر الصغير إلى إنشاء مجلد باسم `practice` على سطح المكتب. يمكنك التحقق إذا كان هناك من خلال النظر في سطح المكتب الخاص بك أو بواسطة تشغيل أمر `dir` أو `ls`! جربها. :) + +> نصيحة للمحترفين: إذا كنت لا ترغب في كتابة نفس الأوامر مراراً وتكراراً، حاول الضغط على `سهم للأعلى` و `سهم للأسفل` على لوحة المفاتيح للتنقل عبر الأوامر المستخدمة مؤخرا. + +* * * + +### تمرين! + +تحدي صغيرة بالنسبة لك: في الدليل الذي تم إنشاؤه حديثا `practice` ، قم بإنشاء دليل يسمى `test`(استخدم الأمرين `cd` و `mkdir`.) + +#### الحل: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +تهانينا! :) + +* * * + +### التنظيف + +لا نريد أن تترك فوضى، لذلك دعونا نزيل كل ما قمنا به حتى هذه النقطة. + +أولاً، نحن بحاجة للعودة إلى سطح المكتب: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% filename %}command-line{% endfilename %} + + > cd .. + + + + +استخدام `..` مع أمر `cd` سيغير الدليل الحالي الخاص بك إلى الدليل الأصلي (وهو، الدليل الذي يحتوي على الدليل الحالي الخاص بك). + +تحقق أين أنت: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +حان الوقت الآن لحذف دليل `practice`: + +> **انتباه**: حذف الملفات بإستخدام `del`، `rmdir` أو `rm` غير قابل للإسترداد، مما يعني أن *الملفات المحذوفة ستزول للأبد*! لذا كن حدرا جدا مع هذه الأوامر. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +تم! للتأكد دعونا نتحقق من انك حدفته فعليا: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### الخروج + +هذا كل شيء الأن! يمكنك إغلاق سطر الأوامر الآن بأمان. دعونا نفعل ذلك بطريقة القراصنة، حسناً؟ :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +رائع، هاه؟ :) + +## الملخص + +هنا ملخص لبعض الأوامر المفيدة: + +| الأوامر (في Windows) | الأوامر في (ماك/لينكس) | الوصف | أمثلة | +| -------------------- | ---------------------- | --------------------- | -------------------------------------------------- | +| exit | exit | أغلق النافذة | **exit** | +| cd | cd | تغيير الدليل | **cd test** | +| cd | pwd | إظهار الدليل الحالي | **cd** (Windows) o **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (or del) | rm | حذف الملف | **del c:\test\test.txt** | +| rmdir /S | rm -r | حذف الدليل | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | احصل على مساعدة للأمر | **cd /?** (Windows) أو **man cd** (Mac OS / Linux) | + +هذه فقط عدد قليل جداً من الأوامر التي يمكنك تشغيلها في سطر الأوامر الخاصة بك، ولكنك لن تستخدم أي شيء اكثر من ذلك اليوم. + +إذا كنت فضولياً، [ss64.com](http://ss64.com) يحتوي على مرجع كامل للأوامر لجميع أنظمة التشغيل. + +## مستعد ؟ + +دعونا نغوص في بايثون! \ No newline at end of file diff --git a/ar-SA/intro_to_command_line/open_instructions.md b/ar-SA/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..e50bd708d81 --- /dev/null +++ b/ar-SA/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +اعتماداً على إصدارك من Windows ولوحة المفاتيح الخاصة بك، واحد مما يلي يجب أن يفتح نافذة أمر (قد تضطر إلى تجربة قليلًا)، ولكن ليس عليك تجربة كل هذه المقترحات: + +- انتقل إلى قائمة أو شاشة البدء وأدخل "طلب الأوامر" في حقل البحث. +- اذهب إلى قائمة البدء → نظام ويندوز → طلب الأوامر. +- اذهب إلى قائمة البدء → جميع البرامج → الملحقات → أمر الدفع. +- اذهب إلى شاشة البدء، وقفل الفأرة في الزاوية اليسرى السفلى من الشاشة، وانقر فوق السهم لأسفل الذي يظهر (على شاشة اللمس، بدلا من ذلك ارتفع من أسفل الشاشة). يجب فتح صفحة التطبيقات. انقر على توجيه الأوامر في قسم نظام ويندوز. +- امسك مفتاح ويندوز الخاص على لوحة المفاتيح الخاصة بك واضغط على مفتاح "X". اختر "طلب الأوامر" من القائمة المنبثقة. +- امسك مفتاح ويندوز واضغط على مفتاح "R" للحصول على نافذة "تشغيل". اكتب "cmd" في المربع، وانقر فوق مفتاح OK. + +![أكتب "cmd" في نافدة "Run"](../python_installation/images/windows-plus-r.png) + +في وقت لاحق من هذا البرنامج التعليمي، ستحتاج إلى وجود نافذتين للأوامر مفتوحة في نفس الوقت. ومع ذلك، في بعض إصدارات Windows، إذا كان لديك بالفعل نافذة أمر واحدة مفتوحة وتحاول فتح واحدة ثانية باستخدام نفس الطريقة، وبدلا من ذلك سيوجهك إلى نافذة الأوامر التي لديك بالفعل مفتوحة. جرب الآن على جهاز الكمبيوتر الخاص بك وشاهد ما يحدث! إذا حصلت على نافذة أمر واحدة فقط، جرب إحدى الطرق الأخرى في القائمة أعلاه. وينبغي أن يؤدي واحد منها على الأقل إلى فتح نافذة أوامر جديدة. + + + + + +انتقل إلى التطبيقات → الأدوات المساعدة → تيرمينال. + + + + + +ربما تحت التطبيقات → الملحقات → الطرفية، أو التطبيقات → System → Terminal, ولكن هذا قد يعتمد على النظام الخاص بك. إذا لم يكن هناك ، يمكنك محاولة جوجل. :) + + \ No newline at end of file diff --git a/ar-SA/python_installation/README.md b/ar-SA/python_installation/README.md new file mode 100644 index 00000000000..1cf443314aa --- /dev/null +++ b/ar-SA/python_installation/README.md @@ -0,0 +1,15 @@ +# لنبدأ مع بايثون + +وأخيراً نحن هنا! + +ولكن أولاً، دعونا نقول لكم ما هي بايثون. بايثون هي لغة برمجة شعبية جداً والتي يمكن استخدامها لإنشاء المواقع والألعاب والبرامج العلمية، والرسومات والكثير، أكثر بكثير. + +بايثون نشأت في أواخر الثمانينات، وهدفها الرئيسي أن يتمكن البشر من قراءتها (ليس فقط آلألات!). هذا هو السبب في أنها تبدو أبسط من لغات البرمجة الأخرى، ولكن لا تقلق - بايثون قوية ايضا! + +# تركيب بايثون + +> **ملاحضة**إذا كنت تستخدم كروم بوك تخطى هذا القسم وتابع الإرشادات الموجودة في [التركيب على كروم بوك](../chromebook_setup/README.md). +> +> **ملاحظة** إذا كنت قد عملت بالفعل من خلال [خطوات التثبيت](../installation/README.md)، ليس هناك حاجة للقيام بذلك مرة أخرى - يمكنك التخطي مباشرة إلى الفصل التالي! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/ar-SA/python_installation/instructions.md b/ar-SA/python_installation/instructions.md new file mode 100644 index 00000000000..78d464ffba0 --- /dev/null +++ b/ar-SA/python_installation/instructions.md @@ -0,0 +1,117 @@ +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [تثبيت بايثون محرر التعليمات البرمجية](https://www.youtube.com/watch?v=pVTaqzKZCdA). +> +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots) + +دجانغو مكتوب في بايتون. نحتاج إلى بايثون للقيام بأي شيء في دجانغو. دعونا نبدأ بتثبيته! نريد منك تثبيت أحدث إصدار من Python 3، لذا إذا كان لديك أي إصدار سابق، فستحتاج إلى ترقيته. إذا كان لديك بالفعل الإصدار {{ book.py_min_version }} أو أعلى يجب أن تكون على ما يرام. + +الرجاء تثبيت بايثون العادية كما يلي، حتى عندما يكون لديك أناكوندا مثبت على جهاز الكمبيوتر الخاص بك. + + + +أولاً تحقق مما إذا كان جهاز الكمبيوتر الخاص بك يقوم بتشغيل إصدار 32 بت أو إصدار 64 بت من Windows، على سطر "نوع النظام" من صفحة معلومات النظام. للوصول إلى هذه الصفحة، حاول أحد هذه الأساليب: + +* اضغط على مفتاح ويندوز ومفتاح الإيقاف/الاستراحة في نفس الوقت +* افتح لوحة التحكم الخاصة بك من قائمة ويندوز، ثم انتقل إلى النظام & الأمان، ثم النظام +* اضغط على زر Windows ، ثم انتقل إلى الإعدادات > النظام > حول +* ابحث في قائمة بدء تشغيل ويندوز عن "معلومات النظام". للقيام بذلك، انقر فوق زر البدء أو اضغط على مفتاح ويندوز، ثم ابدأ في كتابة `معلومات النظام`. سوف تبدأ في تقديم الاقتراحات بمجرد أن تكتب. يمكنك اختيار الإدخال بمجرد ظهوره. + +يمكنك تحميل بايثون ل Windows من https://www.python.org/downloads/windows/. انقر فوق "Latest Python 3 Release - Python x.x.x". إذا كان جهاز الكمبيوتر الخاص بك يقوم بتشغيل إصدار **64 بت** من Windows، حمل **Windows x86-64 executable installer**. وبخلاف ذلك، حمل **Windows x86 executable installer**. بعد تحميل المثبت، ينبغي تشغيله (انقر نقراً مزدوجاً على الملف) واتبع الإرشادات الموجودة هناك. + +شيء واحد يجب مراقبته: أثناء التثبيت، ستلاحظ علامة نافذة "الإعداد". تأكد من تحديد مربع الاختيار "إضافة بايثون {{ book.py_version }} إلى باث" أو "إضافة بايثون إلى متغيرات البيئة الخاصة بك" وانقر على "تثبيت الآن"، كما يظهر هنا (قد يبدو مختلفا بعض الشيء إذا كنت تقوم بتثبيت إصدار مختلف): + +![لا تنسى إضافة بايثون إلى المسار](../python_installation/images/python-installation-options.png) + +عند اكتمال التثبيت، قد ترى مربع حوار مع رابط يمكنك متابعته لمعرفة المزيد عن بايثون أو عن الإصدار الذي قمت بتثبيته. إغلاق أو إلغاء مربع الحوار هذا -- سوف تتعلم المزيد في هذا البرنامج التعليمي! + +ملاحظة: إذا كنت تستخدم نسخة قديمة من ويندوز (7، فيستا، أو أي إصدار قديم) وتثبيت Python {{ book.py_version }} فشل بخطأ، قم بتثبيت كافة تحديثات ويندوز وحاول تثبيت بايثون مرة أخرى. إذا كنت لا تزال تعاني من الخطأ، حاول تثبيت إصدار بايثون {{ book.py_min_release }} من [Python.org](https://www.python.org/downloads/windows/). + +> جانغو {{ book.django_version }} يحتاج Python {{ book.py_min_version }} أو أكثر، الذي لا يدعم Windows XP أو الإصدارات السابقة. + + + + + +> **ملاحظة** قبل تثبيت Python على OS X، يجب التأكد من أن إعدادات Mac تسمح بتثبيت الحزم التي ليست من متجر التطبيق. انتقل إلى تفضيلات النظام (هو في مجلد التطبيقات)، انقر فوق "الأمان & الخصوصية"، ثم علامة التبويب "الجنرال". إذا تم تعيين "السماح للتطبيقات التي تم تنزيلها من:" إلى "Mac App Store،" قم بتغييره إلى "Mac App Store والمطورين المحددين." + +يجب عليك زيارة هذا الموقع وتحميل مثبت بايثون https://www.python.org/downloads/mac-osx/: + +* تحميل ملف *مثبت Ma c OS X 64-بت/32-بت * ، +* انقر نقراً مزدوجاً فوق *python-3.6.1-macosx10.6.pkg* لتشغيل المثبت. + + + + + +من المحتمل جدا ان لديك نسخة بايثون مثبتة بالفعل ، للتحقق ادخل الأوامر التالية في وحدة التحكم: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +إذا كان لديك نسخة مختلفة من Python مثبتة، على الأقل {{ book.py_min_version }} ( {{ book.py_min_release }}مثلاً)، فلن تحتاج إلى الترقية. إذا لم يكن لديك Python مثبت، أو إذا كنت تريد إصدار مختلف، فتحقق أولاً من توزيع لينكس الذي تستخدمه مع الأمر التالي: + +{% filename %}command-line{% endfilename %} + + $ تنبيه '^NAME=' /etc/os-release + + +وبعد ذلك، ووفقا للنتيجة، اتبع أحد أدلة التثبيت التالية تحت هذا القسم. + + + + + +استخدم هذا الأمر في وحدة التحكم الخاصة بك: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +استخدم هذا الأمر في وحدة التحكم الخاصة بك: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +إذا كنت تستخدم إصدار فيدورا قديم قد تحصل على خطأ لم يتم العثور على الأمر dnf. في هذه الحالة تحتاج إلى استخدام yum بدلاً من ذلك. + + + + + +استخدم هذا الأمر في وحدة التحكم الخاصة بك: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +تحقق من أن عملية التثبيت كانت ناجحة بفتح موجه الأوامر ثم تشغيل الأمر `python3`: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +قد يكون الإصدار المعروض مختلفا عن {{ book.py_release }} -- يجب أن يتطابق مع الإصدار الذي قمت بتثبيته. + +**ملاحظة:** إذا كنت على Windows وتحصل على رسالة خطأ التي `python3` لم يتم العثور عليها، حاول استخدام `بايثون` (دون `3`) وتحقق مما إذا كان لا يزال إصدار بايثون {{ book.py_min_version }} أو أعلى. إذا لم ينجح ذلك أيضاً، فيمكنك فتح موجه أوامر جديد والمحاولة مرة أخرى؛ يحدث هذا إذا كنت تستخدم موجه أوامر تم فتحه قبل تثبيت بايثون. + +* * * + +إذا كان لديك أي شكوك، أو إذا حدث خطأ ما، وليس لديك أي فكرة عما تفعله بعد ذلك، يرجى سؤال مدربك! أحيانا لا تسير الأمور بسلاسة، لذا من الأفضل أن تطلب المساعدة من شخص لديه خبرة أكبر. \ No newline at end of file diff --git a/ar-SA/python_introduction/README.md b/ar-SA/python_introduction/README.md new file mode 100644 index 00000000000..68f6eebc54a --- /dev/null +++ b/ar-SA/python_introduction/README.md @@ -0,0 +1,1073 @@ +{% set warning_icon = '' %} + +# مقدمة إلى بايثون + +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots). + +دعونا نكتب بعض الأكواد! + +## موجه بايثون + +> للقراء في المنزل: تم تغطية هذا الجزء في فيديو [ أساسيات بايثون: عدد صحيح، سلاسل، قوائم، متغيرات وأخطاء ](https://www.youtube.com/watch?v=MO63L4s-20U). + +من أجل تعلم واللعب بـ بايثون ، علينا أن نفتح *command line* على جهاز الكمبيوتر. من المفترض أنكم تعرفوا كيف تفعلوا ذلك - لقد تعلمتم ذلك في فصل [Intro to Command Line](../intro_to_command_line/README.md) + +بمجرد أن تكونوا جاهزون ، تتبعوا التعليمات التي بالأسفل. + +نريد أن نفتح وحدة تحكم بايثون ، اكتبوا `python` على وندوز أو `python3` على ماك أو لينكس واضغطوا `enter`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## أمر بايثون الأول الخاص بك! + +بعد تشغيل أمر Python ، تغير الموجه إلى `>>>`. هذا يعني أنه حالياً يمكننا فقط إستخدام الأوامر الخاصة بلغة البايثون. لا يتوجب عليكم أن تكتبوا `>>>` - بايثون سوف يفعل ذلك + +إذا كنتم تريدون أن تخرجوا من وحدة تحكم باثون في أي وقت ، اكتبوا `exit()` أو استخدموا الإختصار `Ctrl + Z` في وندوز أو `Ctrl + D` في ماك أو لينكس. لن تروا `>>>` مجدداً + +الآن ، نحن لا نريد الخروج من وحدة تحكم بايثون. نريد أن نتعلم أكثر عنه. دعونا نبدأ بكتابة بعض الرياضيات ، مثل `2 + 3` ونضغط `enter`. + +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +جميل! هل ترون كيف برزت الإجابة؟ بايثون يعرف الرياضيات! يمكنكم تجربة أوامر أخرى مثل: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +إذا كنتم تريدون كتابة معادلات أسية ، مثل 2 أس 3 ، نكتب: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +استمتعوا بهذا لبعض الوقت ثم عودوا إلى هنا. :) + +كما ترون، بايثون آلة حاسبة رائعة. إذا كنت تتساءل عما يمكنك فعله… + +## سلسلة + +ماذا عن اسمك؟ اكتب اسمك الأول في اقتباسات مثل هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" +'Ola' +``` + +لقد أنشأت الآن السلسلة الأولى! هو تسلسل أحرف يمكن معالجتها بواسطة جهاز الكمبيوتر. يجب ان تبدأ السلسلة وتنتهي بنفس الحرف. قد يكون هذا واحد (`'`) أو الضعف (`"`) اقتباس (لا فرق!) الإقتباس يقول لبايثون انه هناك سلسلة. + +السلاسل يمكن أن تكون مربوطة معا. جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +يمكنك أيضا ضرب السلاسل مع عدد: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +إذا كنت بحاجة إلى وضع علامة اقتباس أحادية داخل السلسلة الخاصة بك, لديك طريقتين للقيام بذلك. + +استخدام علامات الاقتباس المزدوجة: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +أو الهروب من الفاصلة بخط مائل (`` \): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +لطيف، هاه؟ لرؤية اسمك بالأحرف الكبيرة، اكتب: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +لقد استخدمت `upper` **method** للتو في السلسلة الخاصة بك! طريقة (مثل `upper()`) هي سلسلة من التعليمات التي يجب على بايثون تنفيذها على شيء معين (`"Ola"`) بمجرد أن تستدعيها. + +إذا كنت تريد أن تعرف عدد الحروف الواردة في اسمك، هناك **function** لذلك أيضا! + +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +هل تتسائلون في بعض الأحيان لماذا تستدعون الدوال مع `.` في نهاية السلسلة مثل `"Ola".upper()` وفي بعض الأحيان تقومون بإستدعاء الدالة وتضعون السلسلة بين قوسين؟ حسنًا، في بعض الحالات، تنتمي الدوال إلى أشياء، مثل `upper()`، والتي لا يمكن القيام بها إلا على السلاسل. في هذه الحالة نسمي المهام ب **method**. مرات أخرى، الدوال لا تنتمي إلى أي شيء محدد ويمكن استخدامها على أنواع مختلفة من الأشياء، تماما مثل `len()`. لهذا نحن نعطي `"Ola"` كعامل متغير إلى الدالة `len`. + +### مُلخّص + +طيب، يكفينا سلآسل ، حتى الأن لقد تعلمت: + +- **the prompt** كتابة الأوامر (كودات) في موجه اوامر بايثون يعطينا اجابات في بايثون +- **numbers and strings** - في بايثون تستخدم الأرقام للرياضيات والسلاسل للكائنات النصية +- **operators** مثل `+` و `*`, تجمع بين القيم لتنتج واحدة جديدة +- **functions** مثل `upper()` و `len()` تنفذ إجراأت على الكائنات. + +هذه هي أساسيات كل لغة برمجة تتعلمها. مستعد لشيء أصعب؟ نحن نراهن بأنك! + +## أخطاء + +لنجرب شيئا جديدا. هل يمكننا الحصول على طول رقم بنفس الطريقة التي يمكننا بها معرفة طول اسمنا؟ اكتب `len(304023)` واضغط `enter`: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> len(304023) +Traceback (most recent call last): +File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +لقد حصلنا على أول خطأ! أيقونة {{ warning_icon }} هي طريقتنا لتنبيهك أن الكود الذي أنت على وشك تشغيله لن يعمل كما هو متوقع. إن ارتكاب الأخطاء (حتى الأخطاء المتعمدة) جزء هام من التعلم! + +يقول أن الأشياء من نوع "int" (الأعداد الصحيحة، الأعداد الكاملة) ليس لها أي طول. إذن ماذا يمكننا أن نفعل الآن؟ ربما يمكننا كتابة رقمنا كسلسلة؟ السلاسل لها طول، أليس كذلك؟ + +{% filename %}command-line{% endfilename %} + +```python +>>> len(str(304023)) +6 +``` + +لقد كان مجدياً! استخدمنا الدالة `str` داخل الدالة `len`. الدالة `str()` تحول كل شي إلى سلاسل. + +- الدالة `str` تحول الأشياء إلى **strings + + - الدالة `int` تحول الأشياء إلى **integers** + + > هام: علينا تحويل الأرقام إلى نص، ولكن لا يمكن بالضرورة تحويل النص إلى أرقام – ماذا ستكون `int('hello')` على أي حال؟ + + ## المتغيرات + + مفهوم هام في البرمجة وهو المتغيرات. المتغير ليس أكثر من اسم لشيء يمكن استخدامه في وقت لاحق. يستخدم المبرمجون هذه المتغيرات لتخزين البيانات، وجعل التعليمات البرمجية الخاصة بهم أكثر قابلية للقراءة، لذا لا يتوجب عليهم أن يتذكروا ماهية الأشياء. + + لنفرض أننا نريد إنشاء متغير جديد يسمى `name`: + + {% filename %}command-line{% endfilename %} + + ```python + >>> name = "Ola" + ``` + + نكتب الاسم يساوي Ola. + + كما لاحظت، لم يعيد برنامجك أي شيء كما فعل من قبل. إذاً كيف نعرف أن المتغير موجود بالفعل؟ أدخل `name` واضغط `enter`: + + {% filename %}command-line{% endfilename %} + + ```python + >>> name + 'Ola' + ``` + + يآآاي! المتغير الأول الخاص بك! :) يمكنك دائماً تغيير ما يشير إليه: + + {% filename %}command-line{% endfilename %} + + ```python + >>> name = "Sonja" + >>> name + 'Sonja' + ``` + + يمكنك استخدامه في الوظائف أيضا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> len(name) + 5 + ``` + + رائع، أليس كذلك؟ بالطبع، المتغيرات يمكن أن تكون أي شيء أرقام أيضا! جرب هذا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> a = 4 + >>> b = 6 + >>> a * b + 24 + ``` + + ولكن ماذا لو استخدمنا اسم خاطئ؟ هل يمكنك تخمين ما يمكن أن يحدث؟ دعونا نحاول! + + {% filename %}{{ warning_icon }} command-line{% endfilename %} + + ```python + >>> city = "Tokyo" + >>> ctiy + Traceback (most recent call last): + File "", line 1, in + NameError: name 'ctiy' is not defined + ``` + + خطأ! كما ترون، بايثون لديه أنواع مختلفة من الأخطاء ويسمى هذا **NameError**. سوف يعطيك بايثون هذا الخطأ إذا حاولت استخدام متغير لم يتم تعريفه بعد. إذا واجهت هذا الخطأ في وقت لاحق، تحقق من التعليمات البرمجية الخاصة بك لمعرفة إذا كنت أخطأت في أي أسماء. + + العب مع هذا لبعض الوقت و شاهد ما يمكنك فعله! + + ## وظيفة الطباعة + + جرب هذا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> name = 'Maria' + >>> name + 'Maria' + >>> print(name) + Maria + ``` + + عندما تكتب فقط `name`، يستجيب مترجم بايثون بالسلسلة *representation* للمتغير 'name', والتي هي الحروف M-a-r-i-a محاطة بعلامة إقتباس واحدة، ''. عندما تقول `print(name)`، بايثون سيقوم ب "طباعة" محتويات المتغير إلى الشاشة، دون علامات الاقتباس، وهو أكثر إتقاناً. + + كما سنرى لاحقا، `print()` مفيد أيضا عندما نريد طباعة الأشياء من داخل الدوال، أو عندما نريد طباعة الأشياء على خطوط متعددة. + + ## القوائم + + بجانب السلاسل والأعداد الصحيحة، بايثون لديه كل الأنواع المختلفة من الكائنات. الآن سوف نقدم واحدة تسمى **list**. القوائم هي بالضبط ما تعتقده: الأشياء التي هي قوائم أشياء أخرى. :) + + امضي قدما وأنشئ قائمة: + + {% filename %}command-line{% endfilename %} + + ```python + >>> [] + [] + ``` + + نعم، هذه القائمة فارغة. ليست مفيدة جدا، أليس كذلك؟ دعونا ننشئ قائمة من أرقام اليانصيب. نحن لا نريد أن نكرر ذالك طوال الوقت، لذلك سنضعها في متغير أيضا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> lottery = [3, 42, 12, 19, 30, 59] + ``` + + حسنا، لدينا قائمة! ماذا يمكننا أن نفعل حيال ذلك؟ دعونا نرى كم عدد اليانصيب هناك في القائمة. هل لديك أي فكرة عن أي وظيفة يجب عليك استخدامها لذلك؟ أنت تعرف هذا بالفعل! + + {% filename %}command-line{% endfilename %} + + ```python + >>> len(lottery) + 6 + ``` + + نعم! `len()` يمكن أن تعطيك عددا من الكائنات في قائمة. مفيد، أليس كذلك؟ ربما سنقوم بترتيبها الآن: + + {% filename %}command-line{% endfilename %} + + ```python + >>> lottery.sort() + ``` + + هذا لا يعيد أي شيء، انها مجرد تغييرات للترتيب الذي يظهر الأرقام في القائمة. دعونا نطبعه مرة أخرى ونرى ما يحدث: + + {% filename %}command-line{% endfilename %} + + ```python + >>> print(lottery) + [3, 12, 19, 30, 42, 59] + ``` + + كما ترون، الأرقام في قائمتك الآن مصنفة من أدنى قيمة إلى أعلى قيمة. تهانينا! + + ربما نريد عكس هذا الترتيب؟ دعونا نفعل ذلك! + + {% filename %}command-line{% endfilename %} + + ```python + >>> lottery.reverse() + >>> print(lottery) + [59, 42, 30, 19, 12, 3] + ``` + + إذا كنت ترغب في إضافة شيء إلى القائمة الخاصة بك، يمكنك فعل ذلك عن طريق كتابة هذا الأمر: + + {% filename %}command-line{% endfilename %} + + ```python + >>> lottery.append(199) + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + ``` + + إذا كنت ترغب في إظهار الرقم الأول فقط، يمكنك القيام بذلك باستخدام **indexes**. الفهرس هو الرقم الذي يقول أين يوجد عنصر في القائمة. المبرمجون يفضلون بدء العد عند 0، لذلك الكائن الأول في قائمتك هو في الفهرس 0، والعنصر التالي هو في 1، وما إلى ذلك. جرب هذا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> print(lottery[0]) + 59 + >>> print(lottery[1]) + 42 + ``` + + كما ترون، يمكنك الوصول إلى كائنات مختلفة في قائمتك باستخدام اسم القائمة وفهرس الكائن داخل الأقواس المعقوفة. + + لحذف شيء من القائمة الخاصة بك سوف تحتاج إلى استخدام **indexes** كما تعلمنا أعلاه وأسلوب `pop()`. دعونا نجرب مثالا ونعزز ما تعلمناه سابقا، سنقوم بحذف العدد الأول من قائمتنا. + + {% filename %}command-line{% endfilename %} + + ```python + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lottery[0]) + 59 + >>> lottery.pop(0) + 59 + >>> print(lottery) + [42, 30, 19, 12, 3, 199] + ``` + + عمل هذا كالسحر ! + + للمتعة الإضافية، حاول بعض الفهارس الأخرى: 6، 7، 1000، -1، -6 أو -1000. انظر إذا كان يمكنك التنبؤ بالنتيجة قبل محاولة الأمر. هل النتائج منطقية؟ + + يمكن أن تجد قائمة بجميع أساليب القائمة المتوفرة في هذا الفصل من وثائق بايثون: https://docs.python.org/3/tutorial/datastructures.html + + ## القواميس + + > للقراء في المنزل: هذا الفصل تم التكلم عنه في [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c). + + القاموس مماثل للقائمة، ولكن يمكنك الوصول إلى القيم عن طريق البحث عن مفتاح بدلا من فهرس رقمي. المفتاح يمكن أن يكون أي سلسلة أو عدد. بناء الجملة لتعريف القاموس الفارغ هو: + + {% filename %}command-line{% endfilename %} + + ```python + >>> {} + {} + ``` + + هذا يدل على أنك قمت بإنشاء قاموس فارغ للتو. يآآاي! + + الآن، حاول كتابة الأمر التالي (حاول استبدال معلوماتك الخاصة أيضا): + + {% filename %}command-line{% endfilename %} + + ```python + >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + ``` + + مع هذا الأمر، قمت للتو بإنشاء متغير يسمى `participant` مع ثلاثة أزواج من القيمة المفتاحية: + + - المفتاح `name` يشير إلى قيمة`'Ola'`(كائن `string`)، + - `country` يشير إلى `'Poland'` (`string` أخرى)، + - ويشير `favorite_numbers` إلى `[7، 42، 92]` (`list` بثلاثة أرقام). + + يمكنك التحقق من محتوى المفاتيح الفردية مع هذه الجملة: + + {% filename %}command-line{% endfilename %} + + ```python + >>> print(participant['name']) + Ola + ``` + + انظر، إنها مشابهة للقائمة. لكنك لست بحاجة إلى تذكر الفهرس - مجرد الاسم. + + ماذا يحدث إذا طلبنا من بايثون قيمة مفتاح غير موجود؟ هل يمكنك التخمين؟ دعونا نحاول ونرى! + + {% filename %}{{ warning_icon }} command-line{% endfilename %} + + ```python + >>> participant['age'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'age' + ``` + + انضر، خطأ آخر! هذا **KeyError**. بايثون مفيد ويخبرك بأن مفتاح `'age'` غير موجود في هذا القاموس. + + متى يجب عليك استخدام القاموس أو القائمة؟ حسناً، هذه نقطة جيدة للتفكير. فكر في الإجابة قبل النظر إليها في السطر التالي. + + - هل تحتاج فقط إلى تسلسل أمر من العناصر؟ انتقل إلى القائمة. + - هل تحتاج إلى ربط القيم مع مفاتيح، حتى تتمكن من البحث عنها بكفاءة (عن طريق مفتاح) في وقت لاحق؟ إستخدم المعجم. + + القواميس، مثل القوائم، هي *mutable*، مما يعني أنه يمكن تغييرها بعد إنشائها. يمكنك إضافة أزواج مفتاح-قيمة جديدة إلى القاموس بعد إنشائه، مثل هذا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> participant['favorite_language'] = 'Python' + ``` + + مثل القوائم، باستخدام طريقة `len()` على القواميس ترجع عدد أزواج القيمة الرئيسية في القاموس. إمضي قدما واكتب هذا الأمر: + + {% filename %}command-line{% endfilename %} + + ```python + >>> len(participant) + 4 + ``` + + آمل أن يكون الأمر منطقيا حتى الآن. :) مستعد لمزيد من المتعة مع القواميس؟ استمر بالقراءة من أجل بعض الأشياء المذهلة. + + يمكنك استخدام طريقة `pop()` لحذف عنصر في القاموس. لنفترض أنك تريد حذف المدخل المقابل للمفتاح `'favorite_numbers'`, ، اكتب فقط الأمر التالي: + + {% filename %}command-line{% endfilename %} + + ```python + >>> participant.pop('favorite_numbers') + [7, 42, 92] + >>> participant + {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} + ``` + + كما ترون من المخرج، تم حذف زوج مفتاح القيمة المقابلة لمفتاح 'favorite_numbers'. + + فضلا عن ذلك، يمكنك أيضا تغيير قيمة مرتبطة بمفتاح تم إنشاؤه مسبقاً في القاموس. اكتب هذا الأمر: + + {% filename %}command-line{% endfilename %} + + ```python + >>> participant['country'] = 'Germany' + >>> participant + {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} + ``` + + كما ترون، تم تغيير قيمة المفتاح `'country'` من `'Poland'` إلى `'Germany'`. :) مثير؟ مرحى! لقد تعلمت للتو شيء آخر مدهش. + + ### الملخص + + مدهش! أنت تعرف الكثير عن البرمجة الآن. لقد تعلمت في هذا الجزء الأخير حول: + + - **أخطاء** – يمكنك الآن معرفة كيفية قراءة وفهم الأخطاء التي تظهر إذا كان بايثون لم يفهم امر اعطيته له + - **المتغيرات** –أسماء الكائنات التي تسمح لك بتكويد أكثر سهولة وجعل التعليمات البرمجية الخاصة بك أكثر قابلية للقراءة + - **قوائم** – قوائم الكائنات المخزنة في ترتيب معين + - **قواميس** – الكائنات المخزنة كقيمة مفتاح-أزواج + + متحمس للجزء القادم؟ :) + + ## مقارنة الأشياء + + > للقراء في المنزل: هذا الفصل تم التكلم عنه في فيديو [Python Basics: Dictionaries](https://www.youtube.com/watch?v=7bzxqIKYgf4). + + جزء كبير من البرمجة ينطوي على مقارنة الأشياء. ما هو أسهل شيء للمقارنة؟ أرقام، بالطبع. دعونا نرى كيف يعمل: + + {% filename %}command-line{% endfilename %} + + ```python + >>> 5 > 2 + True + >>> 3 < 1 + False + >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + >>> 5 != 2 + True + >>> len([1, 2, 3]) > len([4, 5]) + True + ``` + + أعطينا بايثون بعض الأرقام للمقارنة. كما ترون، ليس فقط بايثون يمكن مقارنة الأرقام، ولكن يمكن أيضا مقارنة قيم التعبيرات الرياضية مثل `2 * 2` ونتائج الدالة مثل `2` التي تم إرجاعها بواسطة `len([4, 5]`. رائع، هاه؟ + + هل تتساءل لماذا وضعنا اثنين من العلامات المتساوية `==` بجانب بعضها البعض للمقارنة إذا كانت الأرقام متساوية؟ نحن نستخدم `=` لتعيين القيم للمتغيرات. أنت دائما، **دائما** بحاجة إلى وضع اثنين منها - `==` - إذا كنت ترغب في التحقق مما إذا كانت الأشياء تساوي بعضها البعض. يمكننا أن نقول أيضا أن الأمور غير متساوية مع بعضها البعض. لذالك نستخدم هذه الرموز `!=` كما هو مبين في المثال أعلاه. + + أعطي بايثون مهمتان اخرتان: + + {% filename %}command-line{% endfilename %} + + ```python + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False + ``` + + لقد رأينا `>` و `<`، ولكن ماذا يعني `>=` و `<=` ؟ اقرأهم بهذه الطريقة: + + - `x_>` y يعني: x أكبر من y + - `x_<` y يعني: x أقل من y + - x `<=` y يعني: x أقل من أو يساوي y + - x `> =` يعني y: x أكبر من أو يساوي y + + رائع! تريد القيام بذالك مرة اخرى؟ جرب هذا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> 6 > 2 and 2 < 3 + True + >>> 3 > 2 and 2 < 1 + False + >>> 3 > 2 or 2 < 1 + True + ``` + + يمكنك أن تعطي بايثون العديد من الأرقام للمقارنة كما تريد، وسوف يعطيك الجواب! ذكي جدا، أليس كذلك؟ + + - **و**-إذا قمت باستخدام عامل التشغيل `and`، كل المقارنات يجب أن تكون صحيحة في النظام لكي يكون الأمر كله صحيح + - **أو** – إذا كنت تستخدم عامل التشغيل `or`، واحد فقط من المقارنات يجب أن يكون صحيحاً في النظام لكي يكون الأمر كله صحيح + + هل سمعت عبارة "مقارنة التفاح بالبرتقال"؟ دعونا نجرب ما يعادل هذه العبارة في بايثون: + + {% filename %}{{ warning_icon }} command-line{% endfilename %} + + ```python + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: '>' not supported between instances of 'int' and 'str' + ``` + + هنا ترى أنه كما هو الحال في التعبير، بايثون غير قادر على مقارنة عدد (`int`) وسلسلة (`str`). بدلاً من ذلك، فإنه يظهر **TypeError** ويقول لنا لا يمكن مقارنة هذين النوعين معا. + + ## Boolean + + وبالمناسبة، لقد تعلمت للتو نوع جديد من الكائنات في بايثون. تسمى **Boolean**. + + هناك نوعين فقط من كائنات Boolean: + + - صحيح + - خطأ + + ولكن لكي يفهم بايثون هذا، تحتاج دائما إلى كتابته كـ 'صحيح' (الحرف الأول الكبير، مع بقية الأحرف السفلية). **true, TRUE,، وtRUE لن تنجح – الوحيدة التي ستنجح هي True.** (نفس الأمر ينطبق على 'False' كذلك، بطبيعة الحال.) + + Booleans يمكن أن تكون متغيرات، أيضا! انظر هنا: + + {% filename %}command-line{% endfilename %} + + ```python + >>> a = True + >>> a + True + ``` + + يمكنك أيضا القيام بذلك بهذه الطريقة: + + {% filename %}command-line{% endfilename %} + + ```python + >>> a = 2 > 5 + >>> a + False + ``` + + تدرب واستمتع مع Booleans بمحاولة تشغيل الأوامر التالية: + + - `True and True` + - `False and True` + - `True or 1 == 1` + - `1 != 2` + + تهانينا! Booleans هي واحدة من أروع ميزات البرمجة، وقد تعلمت للتو كيفية استخدامها! + + # احفظه! + + > للقراء في المنزل: هذا الفصل تم التكلم عنه في فيديو [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk). + + حتى الآن كنا نكتب كل ما لدينا من تعليمات بايثون في المترجم، مما يحدنا من إدخال سطر واحد من التعليمات البرمجية في وقت واحد. يتم حفظ البرامج العادية في الملفات ويتم تنفيذها من قبل لغتنا البرمجية **interpreter** أو **compiler**. حتى الآن كنا نقوم بتشغيل برامجنا سطر واحد في كل مرة في بايثون **interpreter**. سنحتاج إلى أكثر من سطر واحد من التعليمات البرمجية للمهام القليلة التالية، لذلك سنحتاج بسرعة إلى: + + - قم بإنهاء مترجم بايثون + - فتح محرر التعليمات البرمجية لدينا الاختيار + - حفظ بعض التعليمات البرمجية في ملف بايثون جديد + - تشغيله! + + للخروج من مترجم بايثون الذي كنا نستخدمه، ببساطة اكتب دالة `exit()` + + {% filename %}command-line{% endfilename %} + + ```python + >>> exit() + $ + ``` + + هذا سيضعك مرة أخرى في موجه الأوامر. + + في وقت سابق، اخترنا محرر التعليمات البرمجية من قسم [code editor](../code_editor/README.md). سنحتاج إلى فتح المحرر الآن وكتابة بعض التعليمات البرمجية في ملف جديد (أو إذا كنت تستخدم كروم بوك، أنشئ ملف جديد في قاعدة البيانات السحابية وافتح الملف، الذي سيكون في محرر التعليمات البرمجية المضمنة): + + {% filename %}editor{% endfilename %} + + ```python + print('Hello, Django girls!') + ``` + + من الواضح أنك مطور بايثون متقن الآن، لذا لا تتردد في كتابة بعض التعليمات البرمجية التي تعلمتها اليوم. + + الآن نحن بحاجة إلى حفظ الملف وإعطائه اسماً وصفياً. دعونا نسمي الملف **python_intro.py** وحفظه إلى سطح المكتب الخاص بك. يمكننا تسمية الملف أي شيء نريده، ولكن الجزء المهم هنا هو التأكد من انتهاء الملف ب **.py**. ويقول امتداد **.py** لنظام التشغيل أن هذا **Python executable file + + > يجب أن تلاحظ واحدة من أروع شيء عن المحررين الأكواد: الألوان! في وحدة تحكم بايثون، كان كل شيء بنفس اللون. الآن يجب أن ترى أن الدالة `print` هي لون مختلف عن السلسلة. وهذا ما يسمى "syntax highlighting"، وهي ميزة مفيدة حقاً عند الترميز. سيعطيك لون الأشياء تلميحات مثل السلاسل غير المغلقة أو الأخطاء المطبعية في اسم الكلمة الرئيسية (مثل `def` في إحدى الدالات، والتي سنراها أدناه). وهذا أحد الأسباب التي تجعلنا نستخدم محرر تعليمات برمجية. :) + + مع حفظ الملف، حان الوقت لتشغيله! باستخدام المهارات التي تعلمتها في قسم سطر الأوامر، استخدم المحطة الطرفية إلى **change directories** إلى سطح المكتب. + + + + على نظام التشغيل ماك، سيبدو الأمر على هذا النحو: + + {% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + + على لينوكس، سيكون مثل هذا: + + {% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + (تذكر أن كلمة "سطح المكتب" قد تترجم إلى لغتك المحلية.) + + + + + + في موجه أوامر Windows، فإنه سيكون مثل هذا: + + {% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + + وفي Windows Powershell، فإنه سيكون مثل هذا: + + {% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + + إذا علقت، اطلب المساعدة. لهذا بالضبط يتواجد المدربون هنا! + + الآن استخدم بايثون لتنفيذ التعليمات البرمجية في ملف مثل هذا: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hello, Django girls! + + + ملاحظة: في ويندوز 'python3' غير معروف كأمر. بدلاً من ذلك، استخدم 'python' لتنفيذ الملف: + + {% filename %}command-line{% endfilename %} + + ```python + > python python_intro.py + ``` + + حسناً! لقد قمت بتشغيل برنامج بايثون الأول الخاص بك والذي تم حفظه في ملف. هذا احساس رائع؟ + + يمكنك الآن الانتقال إلى أداة أساسية في البرمجة: + + ## If … elif … else + + يجب تنفيذ الكثير من الأشياء في التعليمات البرمجية فقط عند استيفاء شروط معينة. وهذا هو السبب في أن بايثون لديها ما يسمى **if statements**. + + استبدال التعليمات البرمجية في ملف **python_intro.py** بهذا: + + {% filename %}python_intro.py{% endfilename %} + + ```python + if 3 > 2: + ``` + + إذا كان لنا أن نحفظ ونشغل هذا، كنا لنرى خطأ مثل هذا: + + {% filename %}{{ warning_icon }} command-line{% endfilename %} + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + + بايثون يتوقع منا إعطاءه مزيد من التعليمات ليتم تنفيذها إذا كان الشرط `3 > 2` يتحول إلى أن يكون صحيحاً (أو `True` لهذه المسألة). دعونا نحاول جعل بايثون يطبع "إنها تعمل!". استبدل التعليمات البرمجية في ملف **python_intro.py** بهذا: + + {% filename %}python_intro.py{% endfilename %} + + ```python + if 3 > 2: + print('It works!') + ``` + + لاحظ كيف قمنا بفصل السطر التالي من التعليمات البرمجية ب 4 مسافات؟ نحن بحاجة إلى القيام بذلك حتى يعرف بايثون ما هي التعليمات البرمجية التي يجب عليه تشغيلها ، إذا كانت النتيجة صحيحة. يمكنك وضع مسافة واحدة لكن اغلب مبرمجي بايثون يستخدمون 4 مسافات ، لجعل الأمور اكثر اناقة. سيتم إحتساب ضغطة Tab واحدة كـ 4 مسافات أيضاً طالما تم تعيين محرر النصوص الخاص بك للقيام بذلك. عندما قمت باختيارك، لا تقم بتغييره! إذا وضعت فراغ بـ 4 مسافات، قم بوضع 4 مسافات لأي فراغ تعمله في المستقبل، أيضاً - عدا ذلك يمكن أن تواجه مشاكل. + + احفظه وقم بتشغيله مرة أخرى: + + {% filename %}command-line{% endfilename %} + + ```python + $ python3 python_intro.py + It works! + ``` + + ملاحظة: تذكر أن 'python3' في Windows، لا يعتبر كأمر. من الآن فصاعدا، غير 'python3' ب 'python' لتشغيل الملف. + + ### ماذا إذا كان الشرط غير صحيح؟ + + في الأمثلة السابقة، تم تنفيذ التعليمات البرمجية فقط عندما كانت الظروف صحيحة. ولكن بايثون تحتوى ايضا على `elif` و `else`: + + {% filename %}python_intro.py{% endfilename %} + + ```python + if 5 > 2: + print('5 is indeed greater than 2') + else: + print('5 is not greater than 2') + ``` + + عند تشغيل هذا سيتم طباعة: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + 5 is indeed greater than 2 + + + إذا كان عدد 2 أكبر من 5، فسيتم تنفيذ الأمر الثاني. دعونا نرى كيف يعمل `elif`: + + {% filename %}python_intro.py{% endfilename %} + + ```python + name = 'Sonja' + if name == 'Ola': + print('Hey Ola!') + elif name == 'Sonja': + print('Hey Sonja!') + else: + print('Hey anonymous!') + ``` + + وتنفذ: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hey Sonja! + + + اترى ما حدث هناك؟ `elif` يسمح لك بإضافة الشروط الإضافية التي يتم تشغيلها في حالة فشل الشروط السابقة. + + يمكنك إضافة العديد من بيانات `elif` كما تريد بعد العبارة الأولى `if` الخاص بك. على سبيل المثال: + + {% 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! :(") + ``` + + بايثون يمر من خلال كل اختبار في التسلسل ويطبع: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Perfect, I can hear all the details + + + ## التعليقات + + التعليقات هي سطور تبدأ ب `#`. يمكنك كتابة ما تريد بعد `#` وسيتجاهل بايثون ذلك. يمكن للتعليقات ان تجعل تعليماتك البرمجية سهلة ليفهمها الأخرين. + + دعونا نرى كيف يبدو ذلك: + + {% 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!") + ``` + + لا تحتاج إلى كتابة تعليق لكل سطر من التعليمات البرمجية، لكنها مفيدة لشرح سبب عمل التعليمات البرمجية الخاصة بك لشيء ما، أو تقديم ملخص عندما تقوم بعمل شيء معقد. + + ### الملخص + + لقد تعلمت في التدريبات القليلة الماضية حول: + + - **مقارنة الأشياء** – في بايثون يمكنك مقارنة الأشياء باستخدام `>`، `> =`, `= =`، `< =`، `<` و `and` مشغلي `or` + - **Boolean** نوع من العناصر التي لا يمكن أن تحتوي إلا على قيمتين: `True` أو `False` + - **حفظ الملفات** – تخزين التعليمات البرمجية في ملفات حيث يمكنك تنفيذ برامج أكبر. + - **if … elif … else** – البيانات التي تسمح لك بتنفيذ التعليمات البرمجية فقط عند استيفاء شروط معينة. + - **التعليقات**-الأسطر التي لن تشغلها بايثون والتي تمكنك من توثيق التعليمات البرمجية الخاصة بك + + حان الوقت للجزء الأخير من هذا الفصل! + + ## الدالات الخاصة بك! + + > للقراء في المنزل: هذا الفصل تم التكلم عنه في فيديو [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0). + + تذكر الدوال مثل `len()` التي يمكنك تنفيذها في بايتون؟ حسنًا، أخبار جيدة - سوف تتعلم كيفية كتابة وظائفك الآن! + + الدالة هي سلسلة من التعليمات التي يجب على بايثون تنفيذها. تبدأ كل وظيفة في بايثون بالكلمة الرئيسية `def`، وتعطى اسما، ويمكن أن تحتوي على بعض المعلمات. لنحاول. استبدل التعليمة البرمجية في **python_intro.py** بما يلي: + + {% filename %}python_intro.py{% endfilename %} + + ```python + def hi(): + print('Hi there!') + print('How are you?') + + hi() + ``` + + حسنا، الدالة الأولى جاهزة! + + قد تتساءل لماذا قمنا بكتابة اسم الدالة في الجزء السفلي من الملف. عندما نكتب `def hi():` والخطوط المعبأة التالية ، هذا هو أننا نكتب تعليمات لما ينبغي أن تقوم به الدالة `H()`. بايثون سيقوم بقراءة وتذكر هذه التعليمات، ولكن لن يتم تشغيل الدالة بعد. لإخبار بايثون أننا نريد تشغيل الدالة، علينا أن نستدعي الدالة بواسطة `hi()`. بايثون يقرأ الملف وينفذه من الأعلى إلى الأسفل، لذا علينا أن نحدد الدالة في الملف قبل أن نسميها. + + لنختبر و نرى ماذا يحدث: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you؟ + + + ملاحظة: إذا كان لا يعمل، لا داعي للذعر! المخارج سوف تساعدك على معرفة السبب: + + - إذا حصلت على `NameError`، فهذا يعني أنك كتبت شيئا خاطئا، لذا يجب عليك التحقق من أنك استخدمت نفس الاسم عند إنشاء الدالة باستخدام `def hi():` وعند الاتصال به `hi()`. + - إذا حصلت على `IndentationError`، تحقق من أن كلا من خطوط <`print` لها نفس المسافة البيضاء في بداية السطر: بايثون يريد أن تكون كل شفرة داخل الدالة محاذية بدقة. + - إذا لم يكن هناك أي إخراج على الإطلاق، تحقق من أن آخر `hi()` *isn't* مسنن - إذا كان كذلك، فسيصبح هذا السطر جزءا من الوظيفة أيضا، ولن يتم تشغيله ابدا. + + دعونا نبني أول وظيفة لدينا مع المعلمات. سوف نغير المثال السابق - الدالة التي تقول "مرحبا" للشخص الذي يديرها - باسم: + + {% filename %}python_intro.py{% endfilename %} + + ```python + def hi(name): + ``` + + كما ترون، أعطينا الآن وظيفتنا معلمة قمنا بتسميتها `name`: + + {% filename %}python_intro.py{% endfilename %} + + ```python + def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + + hi() + ``` + + تذكر: الدالة `print` معبأة بأربعة مسافات داخل `if` . هذا لأن الدالة تعمل عند استيفاء الشرط. لنرى كيف تعمل الآن: + + {% filename %}{{ warning_icon }} 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' + + + عفوا، خطأ. لحسن الحظ، بايثون يعطينا رسالة إعلام خطأ مفيدة جداً. يخبرنا أن الدالة `hi()` (التي حددنا) تحتوي على حجة واحدة مطلوبة (تسمى `name`) وأننا نسينا تمريرها عند إستدعاء الدالة. دعونا نصلحه في الجزء السفلي من الملف: + + {% filename %}python_intro.py{% endfilename %} + + ```python + hi("Ola") + ``` + + وشغله مرة أخرى: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Ola! + + + وإذا قمنا بتغيير الاسم؟ + + {% filename %}python_intro.py{% endfilename %} + + ```python + hi("Sonja") + ``` + + و قم بتشغيلها: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Sonja! + + + والآن، ما رأيك سوف يحدث إذا قمت بكتابة اسم آخر هناك؟ (لا Ola أو Sonja). جرب وانظر إذا كنت على حق. يجب طباعة هذا: + + {% filename %}command-line{% endfilename %} + + Hi anonymous! + + + يبدو رائعا أليس كذالك؟ بهذه الطريقة لا يتوجب عليك أن تكرر نفسك في كل مرة تريد فيها تغيير اسم الشخص الذي يفترض أن تستقبله الدالة. وهذا هو بالضبط لماذا نحن بحاجة إلى وظائف--لا تريد ابدأ تكرار التعليمات البرمجية الخاصة بك! + + دعونا نفعل شيئا أذكى - هناك أسماء أكثر من اثنين، وكتابة شرط لكل واحد سيكون صعبا، أليس كذلك؟ استبدل محتوى الملف الخاص بك بما يلي: + + {% filename %}python_intro.py{% endfilename %} + + ```python + def hi(name): + print('Hi ' + name + '!') + + hi("Rachel") + ``` + + دعونا نستدعي التعليمات البرمجية الآن: + + {% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + + + تهانينا! لقد تعلمت للتو كيفية كتابة الوظائف! :) + + ## الحلقات + + > للقراء في المنزل: هذا الفصل تم التكلم عنه في فيديو [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0). + + هذا هو الجزء الأخير بالفعل. كان ذلك سريعا، أليس كذلك؟ :) + + المبرمجين لا يحبون تكرار أنفسهم. البرمجة هي جعل كل شيء يعمل أوتوماتيكيا، لذلك نحن لا نريد تحية كل شخص باسمه يدويا، أليس كذلك؟ هنا حيث تأتي الحلقات في متناول اليدين. + + لا تزال تذكر القوائم؟ دعونا ننشئ قائمة من الفتيات: + + {% filename %}python_intro.py{% endfilename %} + + ```python + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + ``` + + نحن نريد أن نحيي كل منهم باسمه. لدينا وظيفة `hi` للقيام بذلك، لذلك دعونا نستخدمها في حلقة: + + {% filename %}python_intro.py{% endfilename %} + + ```python + for name in girls: + ``` + + يتصرف بيان `for` بنفس الطريقة التي يتصرف بها بيان `if` ؛ الرمز أدناه يجب أن يكون هناك أربعة مسافات. + + هنا التعليمات البرمجية الكاملة التي سوف تكون في الملف: + + {% filename %}python_intro.py{% endfilename %} + + ```python + def hi(name): + print('Hi ' + name + '!') + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + for name in girls: + hi(name) + print('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 + + + كما ترون، سيتم تكرار كل ما تضعه داخل بيان `for` مع مسافة بادئة لكل عنصر من القائمة `girls`. + + يمكنك أيضا استخدام `for` على الأرقام باستخدام الدالة `range`: + + {% filename %}python_intro.py{% endfilename %} + + ```python + for i in range(1, 6): + print(i) + ``` + + والتي ستطبع: + + {% filename %}command-line{% endfilename %} + + 1 + 2 + 3 + 4 + 5 + + + `range` هي دالة تنشئ قائمة أرقام تتبع واحدة تلو الأخرى (هذه الأرقام مقدمة من قبل كمعلمات). + + لاحظ أن ثاني هذين الرقمين غير مدرجين في القائمة التي يتم إخراجها بواسطة بايثون (بمعنى `range(1, 6)` من 1 إلى 5، ولكن لا يشمل الرقم 6). وذلك لأن "range" نصف مفتوح، وهذا يعني أنه يشمل القيمة الأولى، ولكن ليس الأخيرة. + + ## الملخص + + هذا كل شيء. **You totally rock!** كان هذا فصل صعب، لذلك يجب أن تشعر بالفخر من نفسك. لما وصلت اليه حتى الأن! + + لدروس بايثون الرسمية والكاملة زر https://docs.python.org/3/tutorial/. هذا سوف يعطيك دراسة أكثر شمولا وكاملة للغة. في صحتك:) + + قد ترغب في القيام بشيء آخر لبعض الوقت - تمتد، تتجول قليلا، إراحة عينيك - قبل الذهاب إلى الفصل التالي. :) + + ![كب كيك](images/cupcake.png) \ No newline at end of file diff --git a/ar-SA/template_extending/README.md b/ar-SA/template_extending/README.md new file mode 100644 index 00000000000..ae172cc4da1 --- /dev/null +++ b/ar-SA/template_extending/README.md @@ -0,0 +1,151 @@ +# تمديد القالب + +شيء جميل آخر يقدمه جانغو لك هو **تمديد القالب **. ماذا يعني هذا؟ هذا يعني أنه يمكنك استخدام الأجزاء نفسها من HTML لصفحات مختلفة من موقعك على الويب. + +القوالب تساعدك عندما تريد استخدام نفس الشكل او المعلومات اكثر من مرة او في اكثر من مكان. ليس عليك تكرار نفسك في كل ملف. وإذا كنت ترغب في تغيير شيء ما، ليس عليك تغيره في كل قالب, بل ستغيره في قالب واحد! + +## أنشئ القالب الرئيسي + +القالب الرئيسي هو قالب اساسي والذي ستقوم بتمديده اثناء استخدامه في اي صفحة من موقعك. + +لنقم بإنشاء ملف `base.html` في `blog/templates/blog/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +بعد ذلك افتحه في محرر الأكواد وانسخ كل شي من `post_list.html` إلى ملف `base.html` ، هكذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +ثم في `base.html`، استبدل 1 (كل شيء بين 1 و ``) مع هذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}قد تلاحض ان هذا قد غير `{% for post in posts %}` إلى `{% endfor %}` ب: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %}{% endblock %} +``` + +لكن لماذا؟ لقد انشأت `كتلة`! استخدمت علامة القالب `{% block %}` لإنشاء منطقة التي ستضع فيها إتش تي أم ال HTML. ذاك HTML قادم من قالب اخر الذي قام بتمديد هذا القالب (`base.html`). نحن سنريك طريقة فعل ذالك خلال لحضات. + +والآن احفظ `base.html` وافتح ملفك `blog/templates/blog/post_list.html` مرة أخرى في محرر الأكواد {% raw %}ستحتاج لحدف كل شي فوق `{% for post in posts %}` وتحت `{% endfor %}`. عند الانتهاء من ذلك، الملف سيبدو هكذا:{% endraw %} + +{% filename %}blog/templates/blog/list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +نريد أن نستخدم هذه كجزء من قالبنا لجميع كتل المحتوى. حان الوقت لإضافة علامات الكتل لهذا الملف! + +{% raw %}You تريد لعلامة كتلتك ان تطابق العلامة في ملف `base.html`. تحتاج أيضا ان تشمل كافة التعليمات البرمجية التي تنتمي إليها في كتل المحتوى الخاص بك. للقيام بذلك، ضع كل شيء بين `{% block content %}` و `{% endblock %}`. مثل هذا: {% endraw %} + +{% filename %}blog/templates/blog/list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +بقي شيء واحد فقط. نحن بحاجة إلى ربط هذين القالبين معا. هذا ما نقصد به توسيع القوالب! سنفعل ذلك عن طريق إضافة علامة تمديد إلى بداية الملف. مثال: + +{% filename %}blog/templates/blog/list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +هذا كل شي! احفظ الملف ، وتحقق إذا كان موقعك الإلكتروني ما زال يعمل جيداً. :) + +> اذا حصلت على هذا الخطأ `TemplateDoesNotExist`، وهذا يعني انه ليس هناك ملف`blog/base.html` ولديك `runserver` يشتغل في الكونسول. حاول إيقافه (بالضغط على Ctrl+C - مفتاح التحكم و C معا) وإعادة تشغيله من خلال تشغيل أمر python manage.py runserver .

+ \ No newline at end of file diff --git a/ar-SA/whats_next/README.md b/ar-SA/whats_next/README.md new file mode 100644 index 00000000000..bf4dfc8a2e6 --- /dev/null +++ b/ar-SA/whats_next/README.md @@ -0,0 +1,43 @@ +# ما هي الخطوة التالية؟ + +هنئ نفسك ** أنت رائع تماما ** نحن فخورون بك! <3 + +### ماذا يجب ان تفعل الأن؟ + +خذ راحة واسترخِ! لقد قمت بشيء ضخم حقا. + +بعد ذلك، تأكد من اتباع Django Girls على [ الفيسبوك ](http://facebook.com/djangogirls) أو [ تويتر ](https://twitter.com/djangogirls) للبقاء مطلعا على كل الأحداث. + +### هل يمكنك التوصية بأي موارد إضافية؟ + +نعم! وهناك *الكثير* من الموارد على الإنترنت لتعلم جميع أنواع مهارات البرمجة-- قد يكون شيئاً شاقاً فعلاً أن تعرف الى أين تذهب الآن، لكننا سنوفر لك كل شيء. مهما كانت اهتماماتك قبل أن تأتي إلى Django Girls، ومهما كانت الاهتمامات التي طورتها خلال المحتوى التعليمي، هذه بعض الموارد المجانية (أو الموارد مع مكونات مجانية كبيرة) يمكن أن تستخدمها للوصول إلى حيث تريد. + +#### جانغو + +- كتابنا الآخر، ["جانغو الفتيات التعليمي": ملحقات](https://tutorial-extensions.djangogirls.org/) +- [المحتوى التعليمي الخاص بDjango](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [ابدأ مع دروس الفيديو لDjango](http://www.gettingstartedwithdjango.com/) +- [جانغو لكل الإختصاصات](https://www.coursera.org/specializations/django) - يمكن تدقيق بعض دروس الفيديو مجاناً ويمكنك الحصول على شهادة من كورسيرا عن طريق أخذ هذه الدروس + +#### إتش تي أم ال، سي اس اس وجافا سكريبت + +- [دورة Codecademy في تطوير الويب](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### بايثون + +- [دورة Codecademy بالبايثون](https://www.codecademy.com/learn/learn-python) +- [دورة جوجل بالبايثون](https://developers.google.com/edu/python/) +- [كتاب "تعلم بايثون الطريقة الصعبة"](http://learnpythonthehardway.org/book/) –التدريبات الأولية مجانية +- [دروس المبرمج الجديد](http://newcoder.io/tutorials/) – هذا مجموعة متنوعة من أمثلة عملية عن كيف يمكنك استخدام بايثون +- [edX](https://www.edx.org/course?search_query=python) – يمكنك أخذ معظم الدورات مجاناً، لكن إذا كنت تريد شهادة أو تصديق نحو مؤهل تعليم عالي هذا سيكلف المال +- [مجموعة كورسات بايثون على كورسيرا](https://www.coursera.org/specializations/python)--يمكن أن يكون حضور بعض محاضرات الفيديو مجاناً، ويمكنك الحصول على شهادة كورسيرا بأخذ هذه الدورات +- [بايثون للجميع](https://www.py4e.com/)--نسخة مجانية ومفتوحة من مجموعة كورسات بايثون للجميع على كورسيرا + +#### التعامل مع البيانات + +- [كورس Codecademy في علم البيانات](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – يمكنك أخذ معظم الدورات مجاناً، لكن إذا كنت تريد شهادة أو تصديق نحو مؤهل تعليم عالي هذا سيكلف المال +- [Dataquest](https://www.dataquest.io/)- أول ٣٠ مهمة مجانية + +لا يسعنا إنتظار ما ستفعل بعد! \ No newline at end of file diff --git a/ar/GLOSSARY.md b/ar/GLOSSARY.md new file mode 100644 index 00000000000..5857b137396 --- /dev/null +++ b/ar/GLOSSARY.md @@ -0,0 +1,3 @@ +# محرر الكود + +محرر الكود هو التطبيق الذي يسمح لك بحفظ التعليمات البرمجية الخاصة بك بحيث تكون قادر على العودة إليها في وقت لاحق. ويمكنك معرفة أين يمكن الحصول على واحد من الفصل الخاص [بمحرر الكود](./code_editor/README.md) \ No newline at end of file diff --git a/ar/README.md b/ar/README.md new file mode 100644 index 00000000000..7456fc51b15 --- /dev/null +++ b/ar/README.md @@ -0,0 +1,51 @@ +# دجانغو لتعليم الفتيات + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> تم ترخيص هذا العمل بموجب ترخيص المشاع الإبداعي Attribution-ShareAlike 4.0 الدولي.  لعرض نسخة من هذا الترخيص، تفضل بزيارة https://creativecommons.org/licenses/by-sa/4.0/ + +## مرحبًا + +مرحبا بكم في البرنامج التعليمي فتيات جانغو! نحن سعداء لرؤيتك هنا :) في هذا البرنامج التعليمي، سوف نأخذك في رحلة في عمق وداخل تقنيات الويب، ونقدم لك لمحة عن كل القطع والقطع التي تحتاج تركيبها معا لجعل الويب يعمل هو الأن . + +كما هو الحال مع كل الأشياء غير المعروفة، هذا سيكون مغامرة ولكن لا تقلق، بما انك استخدمت شجاعتك للوصول الى هنا ، فستكون على ما يرام :) + +## المقدمة + +هل شعرت أن العالم يدور أكثر وأكثر حول التكنولوجيا التي لا يمكنك (حتى الآن) فهمها؟ هل تساءلت كيف يمكن إنشاء موقع على شبكة الإنترنت ولكن لم يكن لديك الدافع الكافي للبدء؟ هل فكرت يوما أن عالم البرمجيات معقد للغاية لدرجة انك لن تتمكن من حتى محاولة القيام بشيء بمفردك؟ + +حسنا، لدينا أخبار جيدة لك! البرمجة ليست صعبة كما يبدو وإننا نريد أن نظهر لكم كيف يمكن أن يكون الموضوع مرح. + +هذا التدريب لن يحولك لمبرمج بطريقة سحرية. إذا كنت تريد أن تكون جيد في ذلك، أنت تحتاج إلى أشهر أو حتى سنوات من التعلم والممارسة. ولكن نحن نريد أن نظهر لك أن البرمجة أو إنشاء مواقع الكترونية ليس معقد كما يبدو. سوف نحاول في شرح مختلف الاجزاء، بكل وسعنا، حتى لا تشعر بالخوف تجاه التكنولوجيا. + +ونأمل أن نكون قادرين على أن نجعلكم تحبون التكنولوجيا بقدر ما نحبها نحن! + +## ماذا ستتعلم خلال هذه التدريبات؟ + +بمجرد الانتهاء من البرنامج التعليمي، سيكون لديك تجربة، تطبيق ويب: مدونة خاصة بك. ونحن سوف نعلمك كيفية وضعه على الانترنت،حتى يرى الأخرون عملك! + +سوف تبدو (أكثر أو أقل) مثل هذا: + +![الرقم 0.1](images/application.png) + +> إذا كنت تعمل مع البرنامج التعليمي لوحدك وليس لديك مدرب الذي سوف يساعدك في حالة وجود أي مشكلة، لدينا نظام دردشة بالنسبة لك: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). لقد طلبنا من مدربينا والمتعلمين السابقين ان يحضرو لبعض الوقت ، لتقديم المساعدة للمتعلمين الجدد! لا تتردد في طرح سؤالك هنا! + +حسنا، [ لنبدأ من البداية... ](./how_the_internet_works/README.md) + +## إتبع البرنامج التعليمي في المنزل + +من المدهش أن تشارك في ورشة عمل جانغو للبنات، ولكن نحن ندرك أنه ليس من الممكن دائما الحضور لواحدة. هذا هو السبب في أننا نشجعكم على محاولة اتباع هذا البرنامج التعليمي في المنزل. للقراء في المنزل نحن حاليا نعد أشرطة فيديو التي من شأنها أن تجعل من آلسهل متابعة البرنامج التعليمي لوحدك. نحن لا نزال نعمل على ذالك ، لكن سيكون هناك المزيد من التحديثات في قناة يوتيوب [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed). + +في كل فصل تم تغطيته، هناك ارتباط يشير إلى الفيديو الصحيح. + +## حول المساهمة + +هذا البرنامج التعليمي من طرف [DjangoGirls](https://djangogirls.org/). إذا قمت بالبحث عن أي أخطاء أو ترغب في تحديث البرنامج التعليمي يرجى [اتباع المبادئ التوجيهية للمساهمة](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## هل تريد أن تساعدنا على ترجمة البرنامج التعليمي للغات أخرى؟ + +حاليا، يجري الاحتفاظ بالترجمات على منصة crowdin.com في: + +https://crowdin.com/project/django-girls-tutorial + +إذا لم تكن لغتك موجودة نرجو منك [مراسلتنا](https://github.com/DjangoGirls/tutorial/issues/new) لإضافتها. \ No newline at end of file diff --git a/ar/SUMMARY.md b/ar/SUMMARY.md new file mode 100644 index 00000000000..a11c7b28fc3 --- /dev/null +++ b/ar/SUMMARY.md @@ -0,0 +1,27 @@ +# الملخص + +* [المقدمة](README.md) +* [التثبيت](installation/README.md) +* [التثبيت (كروم بوك)](chromebook_setup/README.md) +* [كيف تعمل الإنترنت](how_the_internet_works/README.md) +* [مقدمة لسطر الأوامر](intro_to_command_line/README.md) +* [تركيب بايثون](python_installation/README.md) +* [محرر الكود](code_editor/README.md) +* [مقدمة إلى بايثون](python_introduction/README.md) +* [ما هو جانغو؟](django/README.md) +* [تركيب دجانغو](django_installation/README.md) +* [مشروعك الأول في دجانغو!](django_start_project/README.md) +* [نماذج دجانغو](django_models/README.md) +* [دجانغو المشرف](django_admin/README.md) +* [الإعداد!](deploy/README.md) +* [روابط دجانغو](django_urls/README.md) +* [وجهات نظر جانغو -وقت الإنشاء!](django_views/README.md) +* [مقدمة إلى HTML](html/README.md) +* [ORM جانغو (Querysets)](django_orm/README.md) +* [البيانات الديناميكية في قوالب](dynamic_data_in_templates/README.md) +* [قوالب دجانغو](django_templates/README.md) +* [إجعله جميلا بإستخدام CSS](css/README.md) +* [تمديد القالب](template_extending/README.md) +* [توسيع التطبيق الخاص بك](extend_your_application/README.md) +* [روابط دجانغو](django_forms/README.md) +* [ما هي الخطوة التالية؟](whats_next/README.md) \ No newline at end of file diff --git a/ar/chromebook_setup/README.md b/ar/chromebook_setup/README.md new file mode 100644 index 00000000000..e72101085fe --- /dev/null +++ b/ar/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# إعداد جهاز كروم بوك + +> **ملاحظة** اذا كنت قد مررت من هذه المرحلة من قبل ، لا تحتاج للقيام بذلك مرة أخرى--يمكنك تخطي هذه المرحلة والإنتقال إلى [مقدمة بايثون](../python_introduction/README.md). + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/ar/chromebook_setup/instructions.md b/ar/chromebook_setup/instructions.md new file mode 100644 index 00000000000..c645cba496f --- /dev/null +++ b/ar/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +يمكنك [تخطي هذا القسم ](http://tutorial.djangogirls.org/en/installation/#install-python) إذا كنت لا تستخدم كروم بوك. إذا كنت كذالك، تجربة التثبيت الخاص بك سوف تكون مختلفة قليلاً. يمكنك تجاهل بقية إرشادات التثبيت. + +### Cloud 9 + +Cloud 9 هو أداة توفر لك محرر للشفرة البرمجية والوصول إلى جهاز كمبيوتر يعمل على شبكة الإنترنت حيث يمكنك تثبيت، وكتابة، وتشغيل البرامج. خلال مدة البرنامج التعليمي، Cloud 9 سيكون بمثابة *الجهاز المحلي* الخاص بك. ستظل تشغل الأوامر في واجهة التيرمينال تماما مثل زملائك على أوس X، أوبونتو، أو ويندوز، ولكن سيتم توصيل التيرمينال بجهاز كمبيوتر قيد التشغيل في مكان آخر سينشئه لك Cloud 9. + +1. تثبيت 9 Cloud من [مخزن ويب الكروم ](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. اذهب إلى [c9.io](https://c9.io) +3. سجل حساب +4. انقر *إنشاء مساحة عمل جديدة* +5. سمه *django-girls* +6. حدد *Blank* (الثاني من اليمين في الصف السفلي مع الشعار البرتقالي) + +الآن سترى واجهة مع الشريط جانبي ونافذة رئيسية كبيرة مع بعض النصوص، ونافذة صغيرة في الجزء السفلي التي تبدو كالتالي: + +{% filename %}Cloud 9{% endfilename %} + + yourusername:~/workspace $ + + +هذه المنطقة السفلية هي *الطرفية*، الخاصة بك التي ستحصل فيها علي Cloud 9 مستعدا بتوجيهاتك. يمكنك تغيير حجم هذه النافذة لجعلها أكبر قليلاً. + +### البيئة الافتراضية + +بيئة افتراضية (وتسمى أيضا فيرتوالينف) هو مثل مربع خاص يمكننا ملئه بأشياء مفيدة مثل اكواد البرمجة من اجل مشروع نعمل عليه. نستخدم البيئة الإفتراضية للحفاض على مجموعة من اكواد البرمجة من مشروع ما ، حتى لا تختلط مع مشاريع اخرى. + +في التيرمينال في الجزء السفلي من واجهة Cloud 9، قم بتشغيل ما يلي: + +{% filename %}Cloud 9{% endfilename %} + + sudo apt update + sudo apt install python3.6-venv + + +اذا لم يعمل معك هذا، اسأل المدرب الخاص بك للحصول على بعض المساعدة. + +وبعد ذلك، قم بتشغيل: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.0 + + +(لاحظ أنه على السطر الأخير نستخدم تيلد تليها علامة متساوية:~=). + +### Github + +إنشاء حساب Github.

+ +### بايثون في كل مكان + +يتضمن برنامج جانغو لتعليم الفتيات قسما حول ما يسمى النشر، وهي عملية أخذ الكود البرمجي الذي يشغل تطبيق الويب ونقلها إلى جهاز كمبيوتر يمكن الوصول إليه بشكل عام (يسمى الخادم) حتى يتمكن غيرك من للناس من أن يرو عملك. + +هذا الجزء غريب بعض الشيء عند تنفيذ البرنامج التعليمي على جهاز كروم بوك بما أننا نستخدم جهاز كمبيوتر موجود على الإنترنت (على سبيل المثال، جهاز كمبيوتر محمول). ومع ذلك، فإنه لا يزال مفيدا، كما يمكننا أن نفكر في Cloud 9 كمساحة عملنا أو جاري العمل او بايثون في كل مكان كمكان لإضهار اشيائنا كلما اصبحت افضل. + +وبالتالي، قم بالتسجيل لحساب "بيثون في أي مكان" جديد في [www.pythonanywhere.com](https://www.pythonanywhere.com). \ No newline at end of file diff --git a/ar/code_editor/README.md b/ar/code_editor/README.md new file mode 100644 index 00000000000..100d22833c1 --- /dev/null +++ b/ar/code_editor/README.md @@ -0,0 +1,11 @@ +# محرر الكود + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [تثبيت بايثون & محرر التعليمات البرمجية](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s). + +أنت على وشك كتابة أول سطر كود خاص بك، لذا حمل برنامج محرر الكود! + +> **ملاحضة**إذا كنت تستخدم كروم بوك تخطى هذا القسم وتابع الإرشادات الموجودة في [التركيب على كروم بوك](../chromebook_setup/README.md). +> +> **ملاحظة** من الممكن أنك فعلت هذا بوقت سابق في فصل التثبيت، بأمكانك تخطي هذا إلى الفصل التالي! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/ar/code_editor/instructions.md b/ar/code_editor/instructions.md new file mode 100644 index 00000000000..7e6607883de --- /dev/null +++ b/ar/code_editor/instructions.md @@ -0,0 +1,31 @@ +يوجد العديد من برامج التحرير لكن الخيار الاخير يعود للشخص. اغلب مبرمجي البايثون (Python) يستخدمون بيئات تطوير مدمجة (او IDEs) مثل 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/). هو حر ومفتوح المصدر، وسهل التركيب والاستخدام. متاح لويندوز وماك و لينكس. + +[يمكنك تحميل البرنامج هنا](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/ar/css/README.md b/ar/css/README.md new file mode 100644 index 00000000000..63916c7c6b7 --- /dev/null +++ b/ar/css/README.md @@ -0,0 +1,303 @@ +# إجعله جميلا بإستخدام CSS! + +مدونتنا لا تزال تبدو قبيحة جداً، أليس كذلك؟ حان الوقت لجعلها جميلة! سوف نجعلها جميلة بإستخدام CSS. + +## ما هي تقنية CSS؟ + +CSS هي لغة تجميل المواقع, تخيل HTML هي هيكل المنزل يعني الحائط و السارية و السقف و CSS هي الصباغة و الصقل والديكور... و ما إلى ذلك , يعني مثل المكياج + +لكننا لا نريد أن نبدأ من الصفر مرة أخرى، أليس كذلك؟ مرة أخرى، سنستخدم شيئا خلقه المبرمجون على الإنترنت مجانا. إعادة اختراع العجلة ليس ممتعا، كما تعلمون. + +## لنستخدم Bootstrap! + +Bootstrap اطار عمل الأكثر شعبية لـ HTML و CSS لتطوير مواقع جميلة: https://getbootstrap.com/ + +كتب بواسطة المبرمجين الذين عملوا على تويتر والآن يتم تطويره من قبل المتطوعين من جميع أنحاء العالم! + +## تثبيت Bootstrap + +لتثبيت بوتستراب، يجب إضافة هذا إلى `` في ملف `.html :

+ +

{% filename %}blog/templates/blog/post_list.html{% endfilename %}

+ +

+
+`
+ +هذا لا يضيف أي ملفات إلى المشروع الخاص بك. بل يشير فقط إلى الملفات الموجودة على شبكة الإنترنت. افتح موقع الويب الخاص بك وقم بتحديث الصفحة. لاحظت الفرق! + +![الرقم 14.1](images/bootstrap1.png) + +يبدو اجمل الان! + +## الملفات الثابتة في Django + +اخيراً سوف نمعن بالنظر على ما اسميناه **بالملفات الثابتة**. الملفات الثابتة هي كل CSS والصور. محتواهم لا يعتمد على خاصية الطلب وسيكون مشابها عند الجميع. + +### اين توضع الملفات الثابتة لمشروع Django + +جانغو عرف مسبقا أين يجد الملفات الثابتة للتطبيق المضمن المدير "admin". الأن لايلزمنا سوى اضافة بعض الملفات الثابتة للتطبيق الخاص بنا,`blog`. + +نقوم بذلك بانشاء مجلد نسميه `static` داخل تطبيق المدونة: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │ └── templates + └── mysite + + +جانغو سيجد تلقائيا أي مجلد باسم "static" داخل اي مجلد يحتويه تطبيقك. وسيستطيع استعمال محتوياته كملفات ثابتة. + +## الأن مع ملفات CSS + +لنقم بانشاء ملف نمطي CSS. لتظيف تعديلاتك الخاصة لموقعك. قم بانشاء مجلد باسم `css` داخل مجلد `static`. قم بانشاء ملف باسم `blog.css` داخل المجلد `css`. مستعد ؟ + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +حان الوقت للقيام بكتابة بعض CSS,قم بفتح الملف `blog/static/css/blog.css` داخل المحرر. + +لن نذهب عميقاً في تخصيص وتعلم CSS هنا. هناك توصية بدورة CSS مجانية في نهاية هذه الصفحة إذا كنت ترغب في معرفة المزيد. + +لكن لنقم بالقليل على الاقل. ربما نريد تغيير لون الترويسة؟ لفهم الالوان, الحاسوب يستعمل شيفرات خاصة. الشيفرات تبتدأ ب `#` و تليها 6 حروف (A-F) و أرقام (0-9). مثلا ، رمز اللون الأزرق هو `#0000FF`. يمكنك العثور على هذه الشيفرات في هذا الموقع: http://www.colorpicker.com/. يمكنك استعمال الالوان المحددة مسبقا ك `red` و `green`. + +داخل الملف `blog/static/css/blog.css` يجب عليك اضافة التعليمات البرمجية التالية: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a { + color: #FCA205; +} +``` + +`h1 a` هو محدد CSS. وهذا يعني أننا تقوم بتطبيقالأنماط لدينا لأي ` عنصر داخل عنصر h1`. حتى عندما يكون لدينا شيء مثل `

link

`، `h1` سيتم تطبيق النمط. في هذه الحالة نأمرها بتغيير الون الى `#FCA205`,وهو اللون البرتقالي. بالطبع تستطيع وضع أي لون تريد! + +داخل ملف CSS نحدد أنماط العناصر التي توجد داخل ملف HTML. الطريقة الأولى التي نستخدمها لتحديد العناصر هي عبر الإسم. يمكن أن تذكر هذه tags من قسم HTML. أشياء مثل`a`, `h1` و `body` هي كلها امثلة لأسماء العناصر. نحن نحدد العناصر ايضا عبر `class` او عبر `id`. Class و id هي الأسماء التي يمكنك إعطائها للعنصر بنفسك. تحدد class مجموعات من العناصر، و id تشير إلى عناصر محددة. على سبيل المثال، يمكن تحديد tag التالية باستخدام سمة `a`, المصنف `external_link` (class), أو المعرف `link_to_wiki_page` (id): + +```html + +``` + +اقرأ عن [محددات CSS في w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +نحن بحاجة إلى أن نقول أيضا لقالب HTML أننا أضفنا بعض ال CSS. افتح الملف `blog/templates/blog/post_list.html` وأضف هذا السطر في البداية: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load staticfiles %} +``` + +نحن فقط نحمل الملفات الثابتة هنا ما بين علامات `` و `` بعد الارتباطات بملفات بوتستراب CSS ، قم بإضافة هذا السطر: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +المتصفح يقرأ الأوامر بالترتيب الذي اعطي له ، لذا يجب علينا التأكد من ان هذا في المكان الصحيح. وإلا فإن الكود في الملف الخاص بك قد يتم تجاوزه بواسطة الكود في ملفات بوتستراب. قمنا لتونا بإعلام القالب أين توجد ملفات التنسيق CSS. + +الآن يجب أن يبدو الملف الخاص بك مثل هذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +حسنا، قم بحفظ الملف وقم بتحديث الموقع! + +![الرقم 14.2](images/color2.png) + +عمل جيد! ربما نود أيضا إعطاء موقعنا متنفس وزيادة الهامش على الجانب الأيسر؟ دعونا نحاول هذا! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +قم بإضافة التعديل أعلاه لملف التنسيق CSS, احفض الملف و أنظر النتيجة! + +![الرقم 14.3](images/margin2.png) + +ربما يمكننا تخصيص الخط في عنوان الصفحة لدينا؟ ألصق هذا `< header >` في ملف `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +كما من قبل، تحقق من الأمر والمكان قبل الارتباط بـ `blog/static/css/blog.css`. هذا السطر سيطلب خط يسمى *Lobster* من "خطوط جوجل " (https://www.google.com/fonts). + +أعثر على `h1` إعلان كتلة (التعليمات البرمجية بين الأقواس `{` `}`) في ملف CSS `blog/static/css/blog.css`. الآن قم بإضافة السطر `font-family: 'Lobster';` بين أقواس، وحدث الصفحة: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` + +![الرقم 14.3](images/font.png) + +عظيم! + +كما ذكر أعلاه، CSS لديها مفهوم طبقات. هذه تسمح لك بتسمية جزء من التعليمات البرمجية ل HTML وتطبيق الأنماط فقط لهذا الجزء، دون التأثير على الأجزاء الأخرى. هذا يمكن ان يكون مفيد جدا! ربما يكون لديك اثنين من divs اللذان يقومان بشيء مختلف (مثل الهيدر او الموضوع الخاص بك). الكلآس يمكن اي يساعدك في جعلها تبدو مختلفة. + +أمضي قدما وقم بتسمية بعض أجزاء من التعليمات البرمجية ل HTML. إضافة فئة تدعي `page-header` إلى `div` الذي يحتوي الهيدر الخاص بك ، مثل هذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +الان أضف Class `post` إلى `div` الذي يحتوي مقالات المدونة. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +سنقوم الآن بإضافة كتل إعلان لمحددات مختلفة. المحددات التي تبدأ ب `.` تتعلق بالفصول. هناك العديد من الدروس والشروحات التي تتكلم عن CSS في الأنترنت والتي يمكنها مساعدتك على فهم الأكواد التالية. الآن، فقط قم بنسخ ولصق في ملف `blog/static/css/blog.css`: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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 التي تظهر المقالات: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +في `blog/templates/blog/post_list.html` بهذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +إحفظ الملفات الأن، وقم بتحديث موقع الويب الخاص بك. + +![الرقم 14.4](images/final.png) + +وووهووو! يبدو رائعا أليس كذالك؟ انظر إلى التعليمات البرمجية التي ألصقناها للتو للعثور على الأماكن التي أضفنا فيها كلاسات في HTML واستخدمناها في CSS. أين يمكن عمل تعديل ان اردت للوقت ان يكون turquoise؟ + +لا تخافوا من العبث مع هذه CSS قليلا ومحاولة تغيير بعض الأشياء. اللعب ب CSS يمكن أن يساعدك على فهم ما تقوم به الأشياء المختلفة. إذا كسرت شيء لا تقلق يمكنك اصلاحه دائما! + +نحن ننصحك بأخد هذه الحصة التعليمية المجانية [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). يمكن أن تساعدك على تعلم كل شيء عن جعل مواقع الويب الخاصة بك أجمل مع CSS. + +جاهز للفصل التالي؟! :) \ No newline at end of file diff --git a/ar/deploy/README.md b/ar/deploy/README.md new file mode 100644 index 00000000000..5b823135332 --- /dev/null +++ b/ar/deploy/README.md @@ -0,0 +1,227 @@ +# الإعداد! + +> **ملاحظه** الفصل التالي قد يكون في بعض الأحيان صعبا. استمر و أعزم على الانتهاء منه؛ الإعداد جزء هام من عملية تطوير موقع شبكة الإنترنت. ويوضع هذا الفصل في منتصف البرنامج التعليمي حتى يمكن لمدربك أن يساعدك في العمليات الأصعب قليلاً لنشر موقع الويب الخاص بك على الإنترنت. وهذا يعني أنه لا يزال يمكنك الانتهاء من البرنامج التعليمي الخاص بك بمفردك إذا نفذ الوقت منك. + +حتى الأن موقعك كان متاحا فقط على حاسوبك. الأن سوف تتعلم كيف تنشره! الإعداد هو عملية نشر التطبيق الخاص بك على شبكة الإنترنت حيث يمكن للناس الذهاب إلى التطبيق الخاص بك و مشاهدته. :) + +كما تعلمت، موقع على شبكة الإنترنت يجب أن يتواجد في خادم. هناك الكثير من مقدمي الخدمة متاحين على شبكة الإنترنت، ونحن سنستخدم [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere متوفر مجانا للتطبيقات الصغيرة التي لا تحتوي على عدد كبير من الزائرين فالآن بالتأكيد ستكون كافية بالنسبة لك. + +الخدمات الخارجية الأخرى ستقوم باستخدام [GitHub](https://www.github.com)، وهي خدمة استضافة التعليمات البرمجية. هناك آخرون ، ولكن تقريبا جميع المبرمجين لديهم حساب GitHub في هذه الأيام، والآن أنت سوف يمكنك أيضا الحصول على حساب! + +سوف تكون هذه الأماكن الثلاثة هامة بالنسبة لك. الكمبيوتر الخاص بك سوف يكون المكان حيث يمكنك القيام بالتطوير والإختبار. عندما تكون راضيا عن التغييرات، ستقوم بوضع نسخة من التعليمات البرمجية على GitHub. موقعك سيكون على بايثون في كل مكان ، وستقوم بتحديثه عبر استقدام نسخة جديدة من GitHub. + +# جيت (Git) + +> **ملاحظة** إذا كنت قمت بإجراء خطوات التثبيت سابقا، لا تحتاج للقيام بذلك مرة أخرى -يمكنك التخطي إلى الجزء التالي والبدء في إنشاء مستودع Git الخاص بك. + +{% include "/deploy/install_git.md" %} + +## ابتداء مستودعك في Git + +Git يتعقب التغييرات التي تحدث لمجموعة معينة من الملفات في ما يسمى بمستودع الكود (أو "الريبو" للاختصار). لنبدأ انشاء مستودع (ريبو) لمشروعنا. افتح وحدة التحكم الخاص بك ، وشغل هذه الأوامر في دليل `djangogirls`: + +> **ملاحظة** تحقق من دليل العمل الحالي الخاص بك مع `pwd` (Mac OS X/لينكس) أو `cd` (في Windows) قبل تهيئة المستودع. يجب أن تكون في المجلد `djangogirls`. + +{% filename %}command-line{% endfilename %} + + $ 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` في الدليل الرئيسي. افتح المحرر الخاص بك وقم بإنشاء ملف جديد مع محتويات التالية: + +{% filename %}.gitignore{% endfilename %} + + * .pyc * ~ + __pycache__ + myvenv db.sqlite3 / static .DS_Store + + +واحفظه ك `.gitignore` في مجلد "djangogirls". + +> **ملاحظة** النقطه في بداية اسم الملف مهمه! إذا كنت تواجه أي صعوبة في انشائه (على سبيل المثال ،أجهزة ماكينتوش لا تمكنك من إنشاء الملفات التي تبدأ بنقطة عن طريق الباحث)، إذا قم باستخدام ميزة "حفظ باسم" في المحرر الخاص بك. +> +> **ملاحظة** أحد الملفات التي قمت بتحديدها في ملف `.gitignore` هي `db.sqlite3`. هذا الملف هو قاعدة البيانات المحلية الخاصة بك، حيث يتم تخزين جميع المشاركات الخاصة بك. لا نريد اضافة هذا الى المستودع الخاص بك ، لأن موقعك على بايثون في كل مكان سيكون يستخدم قاعدة بيانات مختلفة. قاعدة البيانات تلك يمكن ان تكون SQLite, مثل جهاز التطوير الخاص بك ، لكن في العادة ستستخدم واحدة تسمى MySQL, والتي يمكنها التعامل مع الكثير من الزوار اكثر من SQLite. وفي كلتا الحالتين، بتجاهل قاعدة بيانات SQLite للنسخة GitHub، يعني أن جميع المشاركات التي قمت بإنشائها حتى الآن ستبقى و تكون متاحة محلياً، ولكن سيكون عليك اضافتهم مرة اخرى للإنتاج. ينبغي أن تفكر في قاعدة البيانات المحلية الخاصة بك كملعب جيد حيث يمكنك اختبار أشياء مختلفة وولا تخف من فكرة انك ستحدف مشاركاتك الحقيقية من المدونة. + +انها فكرة جيدة استخدام الأمر `git status` قبل `git add` أو كلما وجدت نفسك غير متأكد من ما تغير. وهذا سيساعد على منع أي مفاجآت من الحدوث، مثل إضافة ملفات خاطئة. الأمر `git status` يرجع المعلومات عن اي ملف لم يتم اتباعه تعديله او تنظيمه, حالة الفرع، وأكثر من ذلك بكثير. يجب أن يكون المخرج مشابه لما يلي: + +{% filename %}command-line{% endfilename %} + + $ 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) + + +وأخيرا نحفض التغييرات التي قمنا بها, اذهب الى لوحة التحكم الخاصة بك وشغل هذه الأوامر: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + ## Wypychanie kodu na GitHuba + + Przejdź na [GitHub.com](https://www.github.com) i załóż nowe, darmowe konto użytkonika. (إذا كنت قد سبق أن فعلت ذلك في ورشة العمل الإعدادية، هذا عظيم!) قم بإنشاء مستودع جديد، وإعطائه اسم "my-first-blog". اترك خانة "initialize with a README" دون اختيارها واترك الخيار.gitignore فارغ (لقد فعلنا ذلك يدوياً) وأترك الترخيص على أنه لا شيء. + + > * * ملاحظة * * اسم 'my-first-blog' مهم – يمكن أن تختار شيئا آخر، لكن هذا سيأخد الكثير من الوقت في الإرشادات الموجودة أدناه، وسيكون عليك استبداله كل مرة. ربما من الأسهل الإبقاء على اسم 'بmy-first-blog'. + + في الشاشة التالية، سوف يظهر لك رابط استنساخ المستودع الخاص بك. اختر إصدار "HTTPS"، إنسخه ، وسوف نلصقه في التيرمينال قريبا: الآن نحن بحاجة إلى ربط المستودع على جهاز الكمبيوتر الخاص بك بالمستودع الموجود على GitHub. + + اكتب الأمر التالي في وحدة التحكم الخاصة بك (استبدل '' مع اسم المستخدم الذي قمت بإدخاله عند إنشاء حساب GitHub الخاص بك، ولكن دون أقواس الزاوية):{% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
أدخل اسم المستخدم في GitHub الخاص بك وكلمة المرور، ويجب أن ترى شيئا من هذا القبيل:{% filename %}command-line{% endfilename %} + + +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/hjwp/my-first-blog.git + +- [new branch] master -> master Branch master set up to track remote branch master from origin. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + تعليماتك البرمجية موجودة الأن على GitHub. الذهاب والتحقق من ذلك! ستجد أنها في نهاية الشركة – [Django] (https://github.com/django/django) وفي [دروس جانغو الفتيات] (https://github.com/DjangoGirls/tutorial)، والعديد من مشاريع البرمجيات الكبيرة مفتوحة المصدر الأخرى أيضا تستضيف التعليمات البرمجية الخاصة بهم في GitHub. :) # إنشاء مدونتنا على بايثون في كل مكان > * * ملاحظة * * قد تم إنشاء حساب ببايثون في كل مكان في وقت سابق أثناء خطوات التثبيت – إذا كان الأمر كذلك، لا حاجة للقيام بذلك مرة أخرى. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## سحب التعليمات البرمجية لدينا من بايثون في كل مكان + + عندما تسجل في بايثون في كل مكان سوف يتم اخدك للوحة التحكم. اختر هذا الخيار لتشغيل وحدة تحكم "Bash" – والذي هو اصدار من بايثون في كل مكان للوحة التحكم، تماما مثل الموجود على حاسوبك. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> > * * ملاحظة * * "بايثون في كل مكان " يستند على لينكس، حتى إذا كنت على ويندوز، وحدة التحكم سوف تبدو مختلفة قليلاً من التي تتواجد على حاسوبك الخاص. + + دعونا نسحب تعليماتنا البرمجية من GitHub وعلى بايثون في كل مكان عن طريق إنشاء "استنساخ" لمستودعنا. اكتب الأمر التالي في وحدة التحكم على بايثون في كل مكان (لا تنسى أن استخدام اسم المستخدم الخاص بك في GitHub بدلاً من `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
هذا سيستنسخ نسخة من تعليماتك البرمجية في بايثون في كل مكان ، يمكنك تفقد ذالك عبر كتابة `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### إنشاء بيئة افتراضية على بايثون في كل مكان + فقط كما فعلت على حاسوبك ، يمكنك انشاء بيئة افتراضية على بايثون في كل مكان. في نافذة وحدة التحكم، اكتب + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> * * ملاحظة * * الخطوة 'pip install' يمكن أن تستغرق بضع دقائق. الصبر والصبر! ولكن إذا إستغرق الأمر أكثر من خمس دقائق، هناك خطأ ما. اسأل المدرب الخاص بك. + + <!-TODO: التفكير في استخدام requirements.txt بدلاً من pip install.--> # # # إنشاء قاعدة بيانات بايثون في كل مكان + هنا شيء آخر مختلف بين الكمبيوتر الخاص بك والخادم: إنه يستخدم قاعدة بيانات مختلفة. حيث يمكن أن تكون حسابات المستخدم ومشاركاته مختلفة على الملقم وعلى الكمبيوتر الخاص بك. + + تماما كما فعلنا على جهاز الكمبيوتر الخاص بك، نحن سنكرر الخطوة لتهيئة قاعدة البيانات على الملقم، عبر `migrate` و `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(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** (ملحوظة:-*not* الخيار "Django") في مربع الحوار. بعد اختيار **Python 3.6**، انقر فوق التالي لإنهاء المعالج. + + > * *ملاحظة* * "تأكد من" اختيار الخيار "Manual configuration"، وليس "Django". نحن نحب جداً الإعداد الافتراضي لدجانغو بايثون في كل مكان. ;-) + ### تعيين البيئة الافتراضية + + سيتم نقلك لصفحة تعديل بايثون في كل مكان لتطبيقك ، والذي يمكنك من الذهاب لأي مكان والقيام بالتعديلا لتطبيقك على السيرفر. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + في المقطع "Virtualenv"، انقر فوق النص الأحمر الذي يقول "Enter the path to a virtualenv"، وأدخل `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. انقر فوق المربع الأزرق مع علامة اختيار لحفظ المسار قبل الانتقال. + + > * *ملاحظة* * استبدال اسم المستخدم الخاص بك PythonAnywhere حسب الحاجة. إذا قمت بخطأ، PythonAnywhere سوف تظهر لك تحذير. + + + # # # تكوين الملف WSGI + + جانغو يعمل باستخدام "بروتوكول WSGI"، معياراً لخدمة مواقع الويب باستخدام بيثون، الذي يدعم بايثون في كل مكان. الطريقة التي يمكننا تتعديل PythonAnywhere بها للإعتراف بمدونتنا جانغو عن طريق تحرير ملف تعديل WSGI. + + انقر فوق "ملف التكوين WSGI" (في المقطع "تعليمات برمجية" بالقرب من أعلى الصفحة – فإنه سوف يكون المسمى شيئا مثل '/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py')، وسوف يتم نقلك إلى المحرر. + + حدف كافة المحتويات وتغييرها ب + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +عمل الملف هو اخبار بايثون في كل مكان اين يكون تطبيق الويب الخاص بنا ، وما هو اسم ملف اعدادات دجانغو. + +`StaticFilesHandler` هو للتعامل مع CSS. هذا سيهتم بك تلقائيا اثناء التطوير المحلي بواسطة الأمر `runserver`. سنعرف المزيد عن الملفات الثابتة لاحقا في البرنامج التعليمي، عندما نقوم بتحرير CSS لموقعنا. + +إضغط **Save** وثم العودة إلى علامة التبويب **Web**. + +لقد انتهينا جميعا! اضغط على الزر الأخضر الكبير **Reload** وستتمكن من عرض تطبيقك. ستجد رابطا إليه أعلى الصفحة. + +## نصائح لتصحيح الأخطاء + +إذا ضهرت لك اي اخطاء عندما تزور موقعك ، المكان الأول الذي يجب ان تبحث فيه عن معلومات الخطأ لتصحيحه هو **error log**. ستجد رابط لهذا في بايثون في كل مكان [علامة التبويب](https://www.pythonanywhere.com/web_app_setup/). انضر ان كان هناك اي رسائل اخطاء ، الأحدث ستجدهم في الأسفل. وتشمل المشاكل الشائعة: + +- نسيان واحدة من الخطوات التي قمنا بها في وحدة التحكم: إنشاء بيئة افتراضية، وتفعيلها، تثبيت جانغو فيها ، ونقل قاعدة بيانات. + +- القيام بخطأ في البيئة الإفتراضية في علامة التبويب ويب – ستكون هناك عادة ما رسالة خطأ حمراء قليلاً هناك، إذا كان هناك مشكلة. + +- خطأ في ملف التكوين WSGI-هل حصلت على مسار مجلد my-first-blog folder الصحيح؟ + +- هل اخترت نفس نسخة بايثون لبيئتك الإفتراضية ، كما فعلت لتطبيق الويب الخاص بك؟ ينبغي أن يكون 3.6. + +وهناك أيضا بعض [النصائح العامة لتصحيح الأخطاء على ويكي PythonAnywhere](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +وتذكر أن المدرب هنا للمساعدة! + +# أنت على الهواء الأن! + +الصفحة الرئيسية لموقعك يجب ان تقول "لقد عمل" تماما كما تقول على حاسوبك الخاص. حاول إضافة `/admin/` إلى نهاية عنوان URL، وسوف يتم نقلك إلى موقع المشرف. سجل الدخول باستخدام اسم المستخدم وكلمة المرور، وسترى انه يمكنك إضافة منشورات جديدة على الملقم. + +وبمجرد الانتهاء من إنشاء عدد قليل من المنشورات، يمكنك العودة إلى الإعدادات المحلية الخاصه بك (ليس بيثون في كل مكان). من هنا يجب أن تعمل على الإعدادات المحليه لإجراء التغييرات. هذا هو سير العمل المشترك في تطوير الإنترنت ـ إجراء تغييرات محليا، ودفع تلك التغييرات إلى GitHub، وسحب التغييرات الخاصة بك وصولا إلى خادم الويب الحي. هذا يسمح لك بالعمل والتجربة دون تحطيم موقع الويب الخاص بك. رائع! اليس كذالك؟ + +إعطي نفسك تربيت *كبير* على الظهر! النشر علي الملقم هو واحد من أصعب أجزاءتطوير الشبكة، وغالبا ما يستغرق الناس عدة أيام قبل أن يجعلوه يعمل. لكنك قد وضعت موقعك على الهواء ، بهذا النحو! \ No newline at end of file diff --git a/ar/deploy/install_git.md b/ar/deploy/install_git.md new file mode 100644 index 00000000000..390a900f486 --- /dev/null +++ b/ar/deploy/install_git.md @@ -0,0 +1,52 @@ +Git عباره عن "نظام تحكم إصدار" مستخدم من قبل الكثير من المبرمجين. هذا النظام يمكنه تعقب التغييرات في الملفات مع مرور الوقت حتى أنه يمكنك استرجاع إصدارات محددة في وقت لاحق. يشبع قليلاً ميزة "تعقب التغييرات" في Microsoft Word، لكن أقوى بكثير. + +## تثبيت Git + + + +يمكنك تحميل Git من [ git-scm.com](https://git-scm.com/). يمكنك الضغط على "التالي" في جميع الخطوات باستثناء خطوة واحدة؛ في الخطوة الخامسة بعنوان "التكيف مع بيئة المسار الخاص بك"، اختر "تشغيل Git وأدوات يونيكس المرتبطة بها من سطر الأوامر في ويندوز" (الخيار الأسفل). بخلاف ذلك، الإعدادات الافتراضية كافيه. راجع نهايات السطور في نمط ويندوز ، و ارتكاب نمط يونكس. + +لا تنس إعادة تشغيل موجه الأوامر أو powershell بعد انتهاء عملية التثبيت بنجاح. + + + +تحميل Git من [.git-scm.com](https://git-scm.com/) واتبع التعليمات. + +> **ملاحضة** إذا كنت تستخدم نضام ماك بهذه الإصدارات OS X 10.6, 10.7, or 10.8, يجب عليك تنصيب نسخة جيت من هذا الرابط [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/ar/deploy/signup_pythonanywhere.md b/ar/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..86fb69565a3 --- /dev/null +++ b/ar/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +التالي،حان الوقت للتسجيل للحصول على حساب مجاني "مبتدئ" في PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **ملاحظة** عند اختيار اسم المستخدم الخاص بك هنا، ضع في اعتبارك أن الموقع (URL) الخاص بك سوف يتخذ شكل `yourusername.pythonanywhere.com`،إذا أما أن تختار الاسم المستعار الخاص بك، أو اسم يليق بالموقع الخاص بك. \ No newline at end of file diff --git a/ar/django/README.md b/ar/django/README.md new file mode 100644 index 00000000000..5e2d4539b63 --- /dev/null +++ b/ar/django/README.md @@ -0,0 +1,27 @@ +# ما هو جانغو؟ + +جانغو (/ˈdʒæŋɡoʊ/*جانغ-جوه*) إطار تطبيق ويب حر ومفتوح المصدر مكتوب بلغة بايثون. أطار العمل مكون من مجموعه من المكونات التى سوف تساعدك على تطوير المواقع بطريقة اسهل واسرع. + +عندما تقوم ببناء موقع على شبكة الإنترنت، تحتاج دائماً مجموعة مماثلة من المكونات: طريقة للتعامل مع مصادقة المستخدم (التسجيل، الدخول، والخروج)، وصفحة إدارية لموقع الويب الخاص بك، والاستمارات، وطريقة لتحميل الملفات، إلخ. + +لحسن الحظ لاحظ أشخاص آخرين منذ وقت طويل أن مطوري الويب تواجههم مشاكل مماثلة عند إنشاء موقع جديد، فتعاونوا في إنشاء أطارات عمل (جانغو واحد منهم) التي تعطيك مكونات جاهزة يمكنك استخدامها. + +اطارات العمل موجودة لتنقدكم من إعادة اختراع ما تم اختراعه من قبل، وتساعد في تخفيف بعض النفقات العامة عندما تقوم ببناء موقع جديد. + +## لماذا تحتاج إلى إطار عمل؟ + +لفهم ما هو جانغو في الواقع ، علينا أن نلقي نظرة فاحصة على الملقمات. أول شيء أن الملقم يحتاج إلى معرفة أن كنت تريد منه ان يعطيك صفحة انترنت. + +تخيل علبة بريد (ميناء) التي يتم ضبطها للرسائل الواردة (الطلبات). وهذا يتم عن طريق خادم ويب. خادم الويب يقوم بقراءة الرسالة وثم يرسل استجابة مع صفحة ويب. ولكن عندما تريد أن ترسل شيئا، فأنت بحاجة إلى بعض المحتوى. وجانغو هو الشيء الذي يساعدك في إنشاء المحتوى. + +## ماذا يحدث عندما يطلب شخص ما موقع انترنت من خادمك؟ + +عندما يصل طلب إلى الخادم ، يتم تمريره لدجانغو ، والذي سيحاول ما الذي تم طلبه. إنه يأخذ عنوان صفحة ويب أولا ويحاول معرفة ما يجب القيام به. يتم هذا الجزء من قبل دجانغو ** urlresolver** (لاحظ أن عنوان موقع ويب يسمى URL - محدد مواقع الموارد - لذلك الاسم * urlresolver * منطقي). أنه ليس ذكية جدا - فإنه يأخذ قائمة من الأنماط ويحاول مطابقة عنوان URL. جانغو يتحقق من الأنماط من أعلى إلى أسفل، وإذا تم مطابقة شيء، يقوم جانغو بتمرير الطلب إلى الدالة المرتبطة بها (والتي تسمى *view*). + +تخيل ناقل البريد مع رسالة. تتمشى في الشارع وتفحص جميع ارقام البيوت مع الرقم الموجود في الرسالة. اذا كان مطابقا ، تضع الرسالة هناك. هذه هي الطريقة التي يعمل urlresolver بها! + +في الدالة *view*، تتم جميع الأمور المثيرة للاهتمام: يمكننا أن ننظر إلى قاعدة بيانات للبحث عن بعض المعلومات. ربما طلب المستخدم بتغيير شيء ما في البيانات؟ مثلما تقول الرسالة: "يرجى تغيير وصف وظيفتي". يمكن ل * view* التحقق مما إذا كان مسموحا لك القيام بذلك، ثم تحديث الوصف الوظيفي لك وإرسال رسالة مرة أخرى: "تم!" ثم * view* يولد استجابة و جانغو يمكن أن يرسلها إلى متصفح الويب الخاص بالمستخدم. + +بالطبع الوصف اعلاه مبسط كثيرا ، لكنك لست في حاجة لمعرفة كل المعلومات التقنية حاليا ، الحصول على فكرة عامة كافي. + +لذلك بدلا من الغوص كثيرا في التفاصيل، نحن سوف نبدأ ببساطة بخلق شيء عبر جانغو وسوف نتعلم كل الأجزاء الهامة على طول الطريق! \ No newline at end of file diff --git a/ar/django_admin/README.md b/ar/django_admin/README.md new file mode 100644 index 00000000000..6db3cfe861d --- /dev/null +++ b/ar/django_admin/README.md @@ -0,0 +1,57 @@ +# دجانغو المشرف + +لإضافة وتعديل وحذف المشاركات التي قمنا بإضافتها، سوف نستخدم دجانغو المشرف. + +دعونا نفتح `blog/admin.py` ونغير محتواه بهذا: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +كما ترون، نقوم باستيراد (تضمين) نموذج المشاركة المحدد في الفصل السابق. لجعل نموذجنا مرئيا على صفحة المشرف، نحن بحاجة إلى تسجيل النموذج مع `admin.site.register(Post)`. + +حسنا حان الوقت للنظر في نموذجنا. تذكر أن تقوم بتشغيل `python manage.py runserver` في وحدة التحكم لتشغيل خادم ويب. اذهب إلى المتصفح واكتب http://127.0.0.1:8000/admin/. ستظهر لك صفحة تسجيل دخول مثل هذه: + +![صفحة تسجيل الدّخول](images/login_page2.png) + +لتسجيل الدخول، تحتاج إلى إنشاء مستخدم *superuser*-حساب مستخدم له السيطرة على كل شيء في الموقع. ارجع إلى سطر الأوامر، واكتب `python manage.py createsuperuser`,، ثم اضغط على إنتر. + +> تذكر، لكتابة الأوامر الجديدة أثناء تشغيل خادم الويب، إفتح نافذة جديدة وفعل البيئة الإفتراضية الخاصة بك. علينا إعادة النظر في كيفية كتابة أوامر جديدة خلال فصل **أول مشروع جانغو لك!** ، في المقطع **بدء تشغيل خادم ويب**. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +عند الطلب، اكتب اسم المستخدم (أحرف صغيرة، لا مسافات)، وعنوان البريد الإلكتروني، وكلمة المرور. **لا تقلق أن كنت لا تستطيع رؤية كلمة المرور التي تكتبها – هكذا يجب ان تعمل-** اكتب فقط واضغط `إدخال` للمواصلة. يجب أن يظهر الناتج على هذا النحو (حيث يجب أن يكون اسم المستخدم والبريد الإلكتروني هو اسم المستخدم الخاص بك): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +ارجع إلى المتصفح. سجل الدخول باستخدام بيانات اعتماد المستخدم الخارق التي اخترتها؛ يجب أن ترى لوحة قيادة دجانغو المشرف. + +![دجانغو المشرف](images/django_admin3.png) + +انتقل إلى المشاركات وقم ببعض الإختبارات هناك. أضف خمس أو ست مشاركات مدونة. لا تقلق بشأن المحتوى - يمكنك ببساطة نسخ ولصق بعض النص من هذا البرنامج التعليمي لتوفير الوقت. :) + +تأكد من أن اثنين أو ثلاث مشاركات على الأقل (ليس جميعها) لها تاريخ نشر. سوف يكون هذا مفيد لنا في وقت لاحق. + +![دجانغو المشرف](images/edit_post3.png) + +إعرف المزيد حول لوحة تحكم دجانغو من خلال قراءة الوثائق الرسمية: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +ربما تكون هذه لحظة جيدة لشرب كوب من القهوة (أو الشاي) أو لتناول الطعام لإعادة تنشيط نفسك. لقد قمت بإنشاء أول نموذج جانغو خاص بك أنت تستحق الإستراحة قليلا! \ No newline at end of file diff --git a/ar/django_forms/README.md b/ar/django_forms/README.md new file mode 100644 index 00000000000..73883e794d0 --- /dev/null +++ b/ar/django_forms/README.md @@ -0,0 +1,447 @@ +# أشكال دجانغو + +الشيء الأخير الذي نريد القيام به على موقعنا هو خلق وسيلة لطيفة لإضافة وتحرير مشاركات مدونتنا. دجانغو `admin` جميل ، لكن من الصعب تخصيصه وجعله جميلا. مع `forms` سيكون لدينا سلطة مطلقة على واجهتنا – يمكن أن نفعل أي شيء تقريبا يمكن أن نتصور! + +الشيء الجميل حول أشكال جانغو هو أنه يمكننا تخصيص واحد من الصفر أو إنشاء `ModelForm` الذي سيحفظ نتيجة النموذج في الشكل. + +هذا بالضبط ما نريد فعله سننشئ شكل لنمودج `Post`. + +مثل كل جزء مهم من دجانغو، فإن النماذج لها ملف خاص بها `forms.py`. + +نحن بحاجة إلى إنشاء ملف بهذا الاسم في دليل `blog`. + + blog + └── forms.py + + +حسنا، دعونا نفتحه ونكتب التعليمة البرمجية التالية: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +نحتاج إلى استيراد أشكال دجانغو أولا (`from django import forms`)، ومن الواضح أن نموذج `Post` من .(`from .models import Post`). + +`PostForm`,، كما كنت تظن ربما، هو اسم النموذج. نحن بحاجة إلى أن نقول لدجانغو ان هذا النموذج هو `ModelForm`(لذلك جانغو ستقوم ببعض السحر `forms.ModelForm` هو المسؤول عن ذلك. + +تاليا ، لدينا `class Meta` والذي يقول لدجانغو اي نمودج يجب استخدامه لإنشاء الشكل (`model = Post`). + +وأخيراً، يمكننا أن نقول ياي حقول يجب ان تنتهي في شكلنا. في هذا السيناريو نريد فقط `title` و `text` عرضه – – `author` ينبغي أن يكون الشخص الذي قام بتسجيل هو (أنت!) ويجب تعيين `created_date` تلقائياً عندما نقوم بإنشاء مشاركة (أي في التعليمات البرمجية)، اليس كذالك؟ + +وهذا كل شيء! كل ما يتعين علينا فعله الآن هو استخدام الشكل في *view* وعرضه في نموذج. + +لذلك مرة أخرى سنقوم بإنشاء رابط إلى صفحة، UR، والعرض والقالب. + +## رابط لصفحة مع الشكل + +حان الوقت لفتح `blog/templates/blog/base.html` سنضيف رابط في `div` بإسم `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +علما اننا سنستدعي العرض الجديد `post_new` كلاس `"glyphicon glyphicon-plus"` موفرة لنا عبر قالب البوستراب الذي نستخدمه. وسوف يضهر علامة + لنا. + +بعد إضافة السطر، الآن يجب أن يبدو ملف HTML الخاص بك مثل هذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +سوف تشاهد بعد حفظ وتحديث الصفحة http://127.0.0.1:8000 من الواضح أن خطأ `NoReverseMatch` مألوف، اليس كذالك؟ + +## عنوان الموقع URL + +نفتح `blog/urls.py` وإضافة سطر: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +سوف تبدو هذه التعليمة البرمجية في النهاية هكذا: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', 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`: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +عندها *view*: الخاصة بنا: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +لإنشاء نموذج `Post` جديد، نحن بحاجة إلى استدعاء `PostForm()` وتمريرها إلى القالب. سنعود لهذا *view* لكن الأن دعونا ننشئ شكل نمودج سريعا. + +## القالب + +نحن بحاجة إلى إنشاء ملف `post_edit.html` في الدليل `blog/templates/blog`. لإنشاء نموذج العمل نحن بحاجة إلى عدة أشياء: + +* علينا عرض الشكل. يمكننا أن نفعل ذلك عبر (على سبيل المثال{% raw %}`{{ form.as_p }}`{% endraw %}. +* السطر أعلاه يحتاج إلى أن يكون ملفوف مع علامة نموذج HTML: `...`. +* ونحن بحاجة إلى زر `Save`. ونحن نفعل ذلك مع زر HTML: ``. +* وأخيراً، فقط بعد افتتاح العلامة `
` نحن بحاجة إلى إضافة {% raw %} `{% csrf_token %}`{% endraw %}. هذا أمر مهم جداً، لأنه يجعل النماذج الخاصة بك آمنة! إذا كنت قد نسيت هذا قليلاً، سيشكو جانغو عند محاولة حفظ النموذج: + +![صفحة "CSFR "](images/csrf2.png) + +حسنا، دعونا نرى كيف يجب ان يبدو `post_edit.html` HTML: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +حان الوقت للتحديث! ياي! تم عرض الشكل الخاص بك! + +![نموذج جديد](images/new_form2.png) + +ولكن انتظر لحظة! عندما تكتب شيئا في حقول `title` و `text` ومحاولة حفظه، ما الذي سيحدث؟ + +لا شيء! نحن مرة أخرى على نفس الصفحة ونصنا قد اختفى.. ولم يتم إضافة أي وظيفة جديدة. ما هو الخطأ؟ + +الجواب: لا شيء. نحن بحاجة إلى العمل أكثر قليلاً في *view*. + +## حفظ الشكل + +أفتح `blog/views.py` مرة أخرى. حاليا كل ما لدينا في `post_new` هو ما يلي: + +{% filename %}blog/views.py{% endfilename %} + +```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* الخاص بنا لدينا حالتين منفصلتين للتعامل معهما: أولا، عندما نصل إلى الصفحة لأول مرة ونريد نموذج فارغ، وثانيا، عندما نعود إلى *view* مع جميع اشكال البيانات التي كتبنا. لذلك نحتاج إلى إضافة شرط (سنستخدم `if` لذلك(: + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +حان الوقت لملئ النقاط `[...]`. إذا كانت `method` `POST` فإننا نريد إنشاء `PostForm` مع بيانات من النموذج، أليس كذلك؟ سوف نفعل ذلك على النحو التالي: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +الشيء التالي هو التحقق مما إذا كان النموذج صحيح (تم تعيين جميع الحقول المطلوبة ولم يتم تقديم أية قيم غير صحيحة). ونحن نفعل ذلك عبر `form.is_valid()`. + +نتحقق مما إذا كان النموذج صالح وإذا كان كذلك، يمكننا حفظه! + +{% filename %}blog/views.py{% endfilename %} + +```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` لمشاركتنا التي تم إنشاؤها حديثا في المدونة، أليس كذلك؟ ولتحقيق ذلك، نحتاج إلى استيراد: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +أضفه في بداية الملف. والآن يمكننا أن نقول: "انتقل إلى صفحة `post_detail` للمشاركة التي تم إنشاؤها حديثا": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` هو اسم العرض الذي نريد الذهاب اليه. تذكر أن هذا *view* يتطلب متغير `pk`؟ لتمريرها إلى العرض، نستخدم `pk=post.pk`، حيث `post` هي مشاركة المدونة التي تم إنشاؤها حديثا! + +حسنا، لقد تحدثنا كثيرا، ولكن ربما نريد أن نرى ما يبدو عليه *view* الآن، أليس كذلك؟ + +{% filename %}blog/views.py{% endfilename %} + +```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`! + +ربما لاحظتم أننا نضع تاريخ النشر قبل حفظ المشاركة. وفي وقت لاحق سوف نقدم *publish button* في **Django Girls Tutorial: Extensions**. + +هذا رائع! + +> كما استخدمنا مؤخرا واجهة المسؤول دجانغو، النظام يعتقد حاليا أننا لازلنا مسجلين. وهناك بعض الحالات التي يمكن أن تؤدي بالنسبة إلى تسجيل الخروج (إغلاق المستعرض، إعادة تشغيل DB، إلخ.). إذا، عند إنشاء مشاركة، أن كنت تحصل على أخطاء في اشارة الى عدم وجود مستخدم سجل الدخول، توجه إلى صفحة المشرف http://127.0.0.1:8000/admin وسجل الدخول مرة أخرى. وهذا سيحل المشكلة مؤقتاً. هناك إصلاح دائم في انتظاركم في فصل **Homework: add security to your website!** بعد البرنامج التعليمي الرئيسي. + +![خطأ في تسجيل الدخول](images/post_create_error.png) + +## التحقق من صحة النموذج + +الأن سنضهر لك كم هي رائعة اشكال دجانغو. المشاركة او التدوينة يجب ان تحتوى على `title` `text`. في نموذج `Post` لم نقول إن هذه الحقول (على عكس `published_date`) غير مطلوبة، لذا يتوقع دجانغو افتراضيا تعيينها. + +حاول حفظ النموذج بدون `title` و `text`. خمن ما سيحدث! + +![التحقق من صحة النموذج](images/form_validation2.png) + +جانغو يحرص على التحقق من صحة جميع الحقول في شكلنا ان كانت صحيحة. أليس هذا رائع؟ + +## تحرير النموذج + +الأن نعرف كيف نضيف شكل جديد. لكن ماذا لو اردنا تحرير شكل موجود مسبقا؟ هذا مشابه جدا لما قمنا به. لنقم بإنشاء بعض الأمور الهامة بسرعة. (إذا كنت لا تفهم شيئا، يجب أن تسأل المدرب الخاص بك أو تنظر في الفصول السابقة، لأننا غطينا جميع هذه الخطوات مسبقاً.) + +افتح `blog/templates/blog/post_detail.html` واضف السطر + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +بحيث يبدو القالب كما يلي: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +وفي `blog/urls.py` نضيف هذا السطر: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +سوف نعيد استخدام القالب `blog/templates/blog/post_edit.html`، آخر شيء مفقود هو طريقة*view*. + +دعونا نفتح `blog/views.py` وإضافة هذا في نهاية الملف: + +{% filename %}blog/views.py{% endfilename %} + +```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` إضافية من عناوين urls. بعد ذلك، نحصل على نموذج `Post` نريد تحرير `get_object_or_404(Post, pk=pk)` وبعد ذلك، عندما نقوم بإنشاء نموذج، نمرر هذه المشاركة باعتبارها `instance`، معا عند حفض النمودج… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +وعنما فتحنا نمودج من هذه المشاركة لتحريره: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +حسنا، دعونا نختبر إذا كان يعمل! لننتقل إلى صفحة `post_detail`. يجب أن يكون هناك زر تعديل في الركن العلوي الأيسر: + +![زر تحرير](images/edit_button2.png) + +عند النقر عليه سترى النموذج مع مشاركة مدونتنا: + +![تحرير النموذج](images/edit_form2.png) + +لا تتردد في تغيير العنوان أو النص وحفظ التغييرات! + +تهانينا! التطبيق الخاص بك يصبح اكثر كمالاً! + +إعرف المزيد حول حول اشكال دجانغو من خلال قراءة الوثائق الرسمية: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## الحماية + +أن تكون قادر على خلق مشاركات جديدة فقط عن طريق النقر على رابط رائع! ولكن في الوقت الراهن، أي شخص يقوم بزيارة موقع الويب الخاص بك سوف يكون قادر على انشاء مشاركة جديدة، وهذا شيء ربما لا تريده. دعونا تجعل الزر يظهر لك و ليس لأي شخص آخر. + +في `blog/templates/blog/base.html`، تجد لدينا `page-header` `div` وعلامة مرساة كانت قد وضعت هناك مسبقا. ينبغي أن تبدو مثل هذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +سنضيف علامة `{% if %}` أخرى ، مما سيجعل الرابط يظهر فقط للمستخدمين الذين سجلوا الدخول إلى المشرف. هذا يعني انت وحدك فقط! غير العلامة ``لتبدو مثل هذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +هذا `{% if %}` سيؤدي إلى إرسال الرابط إلى المتصفح فقط إذا تم تسجيل دخول المستخدم الذي يطلب الصفحة. هذا لا يحمي إنشاء مشاركات جديدة ، ولكنها خطوة أولى جيدة. سنغطي المزيد عن الأمان في الدروس الملحقة القادمة. + +هل تذكر رمز التعديل الذي أضفناه للتو إلى صفحة التفاصيل؟ نريد أيضا إضافة التغيير نفسه هناك، حتى لا يتمكن الأشخاص الآخرون من تعديل المشاركات الحالية. + +افتح `blog/templates/blog/post_detail.html` واضف السطر: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +غيره إلى هذا: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +نظرا لأنك مسجل الدخول، إذا قمت بتحديث الصفحة، فلن ترى شيئا مختلفا. تحميل الصفحة في متصفح مختلف أو نافذة التصفح المتخفي (تسمى "InPrivate" في ويندوز إدج)، على الرغم من ذلك، وسترى أن الرابط لا يضهر والرمز لا يعرض ايضا! + +## شيء اخر: أنشر الوقت! + +دعونا نرى ما إذا كان كل هذا يعمل على PythonAnywhere. حان الوقت لنشر آخر! + +* أولا، التزم بالتعليمات البرمجية الجديدة، وإدفعها إلى جيت هاب: + +{% filename %}command-line{% endfilename %} + + $ 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](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* وأخيرا، انتقل إلى علامة التبويب [Web tab](https://www.pythonanywhere.com/web_app_setup/) واضغط على **Reload**. + +هذا ينبغي ان يكون كل شيء! مبروك:) \ No newline at end of file diff --git a/ar/django_installation/README.md b/ar/django_installation/README.md new file mode 100644 index 00000000000..b8628506b74 --- /dev/null +++ b/ar/django_installation/README.md @@ -0,0 +1,7 @@ +# تركيب دجانغو + +> **ملاحضة**إذا كنت تستخدم كروم بوك تخطى هذا القسم وتابع الإرشادات الموجودة في [التركيب على كروم بوك](../chromebook_setup/README.md). +> +> **ملاحضة** اذا كنت قد عملت على تعليمات التركيب من قبل ، يمكنك الإنتقال الى المستوى الأخر! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/ar/django_installation/instructions.md b/ar/django_installation/instructions.md new file mode 100644 index 00000000000..02ce37f87da --- /dev/null +++ b/ar/django_installation/instructions.md @@ -0,0 +1,201 @@ +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots). +> +> جزء من هذا القسم يستند [django-marcador tutorial](http://django-marcador.keimlink.de/) المرخص لها بمرخصة بموجب المشاع الإبداعي   إسناد-على غرار 4.0 الترخيص الدولي. البرنامج التعليمي django-marcador حقوق الطبع والنشر من قبل Markus Zapke-Gründemann وآخرون. + +## البيئة الافتراضية + +قبل تنصيب دجانغو ، سوف نقوم بتنصيب اداة جد مهمة وستساعدنا كثيرا،في الحفاظ على بيئة كتابة التعليمات البرمجية الخاصة بك مرتبة على جهاز الكمبيوتر. من الممكن تخطي هذه الخطوة، ولكن نحن يوصي بشدة بها. بدءاً من الإعداد الأفضل والذي سيحميك من الكثير من المتاعب في المستقبل! + +هيا لننشئ **بيئة افتراضية** ، تسمى ايضا ب *virtualenv*. سوف تعزل البيئة الإفتراضية إعدادات بايثون / دجانغو الخاص بك على أساس كل مشروع. وهذا يعني أن أية تغييرات تقوم بإجرائها على موقع واحد لن تؤثر على المواقع الأخرى التي تطورها. أنيق، أليس كذالك؟ + +كل ما عليك القيام به هو العثور على الدليل الذي تريد إنشاء `virtualenv`؛ فيه الدليل الرئيسي الخاص بك، على سبيل المثال. في Windows قد تبدو مثل `C:\Users\Name` (حيث `Name` هو اسم تسجيل الدخول الخاص بك). + +> **ملاحظة:** في Windows، تأكد من أن هذا الدليل لا يحتوي على أحرف هجائية أو خاصة؛ إذا كان اسم المستخدم الخاص بك يحتوي على أحرف هجائية، استخدام دليل مختلف، على سبيل المثال `C:\djangogirls`. + +في هذا البرنامج التعليمي سوف نستخدم دليل جديد `djangogirls` من الدليل الرئيسي الخاص بك: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +سوف نقوم بإنشاء بيئة افتراضية تسمى `myvenv`. سوف تكون القيادة العامة في التنسيق: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +لإنشاء `virtualenv`, جديد، تحتاج إلى فتح موجه الأوامر وتشغيل `python -m venv myvenv`. وسوف تبدو كما يلي: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +حيث `myvenv` هو اسم خاص ب `virtualenv`. يمكنك استخدام أي اسم آخر، لكن حافض على الحروف الصغيرة ولا تستخدم مسافات أو لهجات أو أحرف خاصة. كما أنها فكرة جيدة الحفاظ على الاسم قصير – سوف تستخدمه كمرجع كثيرا! + + + + + +يمكننا إنشاء `virtualenv` على لينكس ونظام التشغيلOS X عن طريق تشغيل `python3 -m venv myvenv`: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +حيث `myvenv` هو اسم خاص ب `virtualenv`. يمكنك استخدام أي اسم آخر، لكن حافض على الحروف الصغيرة ولا تستخدم مسافات. كما أنها فكرة جيدة الحفاظ على الاسم قصير – سوف تستخدمه كمرجع كثيرا! + +> **ملاحظة:** في بعض الإصدارات من ديبيان/أوبونتو قد تتلقى الخطأ التالي: +> +> {% filename %}command-line{% endfilename %} +> +> لم يتم إنشاء بالبيئة الإفتراضية بنجاح لأن ensurepip غير متوفر. على أنظمة ديبيان/أوبونتو، تحتاج إلى تثبيت حزمة python3-venv باستخدام الأمر التالي. +> apt-get install python3-venv +> You may need to use sudo with that command. بعد تثبيت حزمة python3-venv، قم بإعادة إنشاء البيئة الإفتراضية الخاصة بك. +> +> +> في هذه الحالة اتبع التعليمات تحت وثبت حزمة `python3-venv` {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **ملاحظة:** في بعض الإصدارات من ديبيان/أوبونتو اعداد البيئة الإفتراضية بهذه الطريقة قد يعطي هذا الخطأ: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> للالتفاف على هذا، استخدم الأمر `virtualenv` بدلاً من ذلك. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **ملاحظة:** إذا حصلت على خطأ مثل +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> قم بتشغيل هذا الأمر: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## العمل مع virtualenv + +الأمر أعلاه سينشئ دليل يسمى `myvenv` (أو أيا كان الاسم الذي تختاره) الذي يحتوي على بيئتنا الإفتراضية (أساسا حفنة من الدلائل والملفات). + + + +بدء تشغيل البيئة الإفتراضية الخاصة بك عن طريق تشغيل: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **ملاحظة:** على Windows 10 قد تحصل على خطأ في Windows PowerShell يقول `execution of scripts is disabled on this system`. وفي هذه الحالة، قم بفتح Windows PowerShell آخر باستخدام الخيار "تشغيل كمسؤول". ثم حاول كتابة الأمر التالي قبل تشغيل البيئة الإفتراضية الخاصة بك: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. تغيير سياسة التنفيذ قد يعرضك للمخاطر الأمنية الموضحة في موضوع التعليمات about_Execution_Policies في http://go.microsoft.com/fwlink/?LinkID=135170. هل تريد تغيير نهج التنفيذ؟ [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +بدء تشغيل البيئة الإفتراضية الخاصة بك عن طريق تشغيل: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +تذكر أن تقوم باستبدال `myvenv` مع الاسم الذي اخترته ل `virtualenv` الخاص بك! + +> **ملاحظة:** في بعض الأحيان قد يكون `source` غير متوفر. وفي تلك الحالات حاول القيام بهذا بدلاً من ذلك: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +سوف تعرف أن لديك `virtualenv` بدأت عندما ترى أن الموجه في وحدة التحكم الخاصة بك مسبوقاً ب `(myvenv)`. + +عند العمل ضمن بيئة افتراضية، سيشير `python` تلقائياً إلى الإصدار الصحيح حيث يمكنك استخدام `python` بدلاً من `python3`. + +حسنا، لدينا كافة التبعيات الهامة في المكان. وأخيراً يمكننا تثبيت جانغو! + +## تثبيت جانغو + +الآن بما انه لديك `virtualenv` مشغل، يمكنك تثبيت جانغو. + +قبل أن نفعل ذلك، يجب علينا التأكد من لدينا أحدث إصدار من `pip`، البرامج التي نستخدمها لتثبيت جانغو: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +قم بتشغيل `pip install django~=1.11.0`(علما بأننا نستخدم تيلدا متبوعاً بعلامة يساوي: `~ =`) لتثبيت جانغو. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> إذا كنت تحصل على خطأ عند استدعاء برنامج pip على منصة Windows، الرجاء التحقق إذا كان اسم مسار المشروع الخاص بك يحتوي على مسافات أو لهجات أو أحرف خاصة (على سبيل المثال، `C:\Users\User Name\djangogirls`). إذا كان كذالك، يرجى النظر في استخدام مكان آخر دون مسافات أو لهجات أو أحرف خاصة (اقتراح: `C:\djangogirls`). إنشاء virtualenv جديدة في الدليل الجديد، ثم إحذف القديم وحاول تنفيذ الأمر أعلاه مرة أخرى. (نقل دليل virtualenv لن يعمل بما ان virtualenv يستخدم مسارات مطلقة.) + + + + + +> سطر الأوامر الخاصة بك قد تجمد بعد محاولة تثبيت جانغو. إذا حدث هذا، بدلاً من الأمر أعلاه استخدم: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> إذا كنت تحصل على خطأ عند استدعاء برنامج pip على أوبونتو 12.04 الرجاء تشغيل `python -m pip install -U --force-reinstall pip` لإصلاح تثبيت برنامج pip في virtualenv. + + + +هذا كل شيء! أنت الآن على استعداد لإنشاء تطبيق جانغو (أخيرا)! \ No newline at end of file diff --git a/ar/django_models/README.md b/ar/django_models/README.md new file mode 100644 index 00000000000..cbb69f06c9c --- /dev/null +++ b/ar/django_models/README.md @@ -0,0 +1,199 @@ +# نماذج دجانغو + +ما نريد أن نخلق الآن هو شيء من شأنه أن يخزن جميع المشاركات في مدونتنا. ولكن لكي نكون قادرين على القيام بذلك، نحتاج إلى الحديث قليلا عن الأشياء المسماة `objects`. + +## الكائنات + +هناك مفهوم في البرمجة يسمى `object-oriented programming`. والفكرة هي أنه بدلاً من كتابة كل شيء كتسلسل ممل من تعليمات البرمجة، يمكننا نمذجة الأشياء وتحديد كيفية تفاعلها مع بعضها البعض. + +ما هو الكائن؟ عبارة عن مجموعة من الخصائص واﻹجراءات. أنها تبدو غريبة، ولكن سوف نقدم لكم بعض الأمثلة. + +إذا أردنا نمذجة قط، سنقوم بإنشاء كائن `Cat` يحتوي على بعض الخصائص مثل `color`, `age`, `mood` (مثل جيد أو سيئ، أو النعاس;))، و `owner`(التي يمكن أن تسند إلى كائن `Person` – أو ربما، في حالة قط ضآل، يمكن أن تكون الخاصية فارغة). + +ثم يحتوي `Cat` على بعض الإجراءات: ` purr أو scratch أو feed (وفي بعض الحالات نعطي القط CatFood ، والتي يمكن أن تكون كائن منفصل مع خصائص، مثل taste ).

+ +
Cat
+--------
+color
+age
+mood
+owner
+purr()
+scratch()
+feed(cat_food)
+`
+ + CatFood + -------- + taste + + +لذا فإن الفكرة الأساسية هي وصف الأشياء الحقيقية في الشفرة مع خصائص (تسمى ` object properties ) والإجراأت (تسمى methods).

+ +

كيف سننشئ مشاركات المدونة بعد ذلك؟ نحن نريد بناء مدونة، أليس كذلك؟

+ +

نحن بحاجة إلى الإجابة على السؤال: ما هي وظيفة المدونة؟ ما هي الخصائص التي يجب ان تحملها؟

+ +

حسنا، بالتأكيد لدينا مشاركة في مدونتنا تحتاج بعض النصوص مع محتوى وعنوان، أليس كذلك؟ سيكون جيدا ايضا معرفة من كتبها ، لذا نحن بحاجة لكاتب. وأخيرا نود معرفة متى تم إنشاء ونشر المشاركة.

+ +
Post
+--------
+title
+text
+author
+created_date
+published_date
+`
+ +ما نوع الأشياء التي يمكن إجراؤها على مشاركة في المدونة؟ سيكون من الجميل أن يكون لديك بعض `method` التي تنشر المشاركة، أليس كذلك؟ + +لذلك سوف نحتاج إلى أسلوب `publish`. + +نظراً لأننا نعرف ما نريد أن نحققه، دعونا نبدأ النمذجة في جانغو! + +## نماذج دجانغو + +بمعرفة ما هو الكائن ، يمكننا انشاء نمودج للمشاركة على مدونتنا. + +النموذج في جانغو هو كائن من نوع خاص يتم حفظه في `database`. قاعدة بيانات هي مجموعة من البيانات. هذا هو المكان الذي ستحفض فيه معلومات حول المستخدمين ،مشاركاتك ومدونتك. سيتم استخدام قاعدة بيانات SQLite لتخزين البيانات الخاصة بنا. هذه قاعدة البيانات الإفتراضية الخاصة بجانغو-- سوف تكون كافية بالنسبة لنا الآن. + +يمكنك التفكير في نموذج في قاعدة البيانات كجدول مع الصفوف (بيانات) والأعمدة (الحقول). + +### إنشاء تطبيق + +لإبقاء كل شيء مرتباً، سننشئ تطبيق منفصل داخل مشروعنا. انه من الجميل ان يكون كل شيء مرتب من البداية. لإنشاء تطبيق نحن بحاجة إلى تشغيل الأمر التالي في وحدة التحكم (من `djangogirls` حيث يوجد الملف `manage.py`): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +ستلاحظ أنه تم إنشاء دليل `blog` جديد ويحتوي على عدد من الملفات الآن. يجب أن تبدو الدلائل والملفات في مشروعنا كما يلي: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +بعد إنشاء التطبيق، نحتاج أيضا أن نقول لدجانغو أنه ينبغي استخدامه. نحن نفعل ذلك في ملف `mysite/settings.py`. نحن بحاجة إلى البحث عن `INSTALLED_APPS` وإضافة خط يحتوي على `'blog',` فقط فوق `]`. المنتج النهائي ينبغي أن يبدو هكذا: + +{% filename %}mysite/settings.py{% endfilename %} + +```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` نحدد كافة كائنات تسمى `Models`--وهذا هو المكان الذي سنحدد فيه مشاركات مدونتنا. + +دعونا نفتح `blog/models.py`، وإزالة كل شيء منه، وكتابة التعليمات البرمجية التالية: + +{% filename %}blog/models.py{% endfilename %} + +```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" (قصيرة ل "double-underscore"). + +يبدو مخيفا، أليس كذلك؟ ولكن لا تقلق--سوف نشرح ماذا تعني هذه السطور! + +جميع الخطوط بدءاً `from` أو `import` هي سطور تضيف بعض أجزاء من ملفات أخرى. بدلاً من نسخ ولصق نفس الأشياء في كل ملف، يمكن أن ندرج بعض الأجزاء مع `من... استيراد...`. + +`class Post(models.Model):` --هذا الخط يحدد نموذج لدينا (و هو`object`).). + +- `class` هي كلمة أساسية خاصة التي تشير إلى أنه علينا تحديد كائن. +- `Post` هو اسم نموذجنا. ويمكننا أن نعطيه اسما مختلفا (ولكن يجب علينا تجنب الأحرف الخاصة والمسافاة). ابدأ دائما بإسم فئة مع حرف كبير. +- `models.Model` يعني أن المشاركة هي نموذج لجانغو، لذلك دجانغو يعرف أنه يجب حفظها في قاعدة البيانات. + +والآن علينا أن نحدد الخصائص التي كنا نتحدث عنها`title`, `text`, `created_date`, `published_date` و `author`. للقيام بذالك نحن بحاجة إلى تحديد نوع كل حقل (النص؟ رقم؟ تاريخ؟ علاقة لكائن آخر، مثل مستخدم) + +- `models.CharField` –--وهكذا يمكنك تحديد نص مع عدد محدود من الأحرف. +- `models.TextField` – هذا لنص طويل دون حد. يبدو مثاليا لمدونة لمشاركة المحتوى، أليس كذلك؟ +- `models.DateTimeField` --هذا هو التاريخ والوقت. +- `models.ForeignKey`--وهذا ارتباط إلى نموذج آخر. + +نحن لن شرح كل شيء من التعليمات البرمجية هنا لأنه سوف يستغرق الكثير من الوقت. ينبغي أن نلقي نظرة على وثائق جانغو إذا كنت ترغب في معرفة المزيد عن حقول النموذج وكيفية تحديد الأشياء غير تلك المذكورة أعلاه (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +وماذا عن `def publish(self):`؟ هذا هو بالضبط الأسلوب `publish` الذي كنا نتحدث عنه. `def` يعني أن هذا أسلوب دالة و `publish` اسم الأسلوب. يمكنك تغيير اسم الأسلوب إذا أردت. حكم التسمية أن نستخدم حروف صغيرة وتسطيرات أسفل السطر بدلاً من المسافات. على سبيل المثال، يمكن استدعاء أسلوب والذي يقوم بحساب متوسط السعر `calculate_average_price`. + +أساليب كثيرا ما `return` شيئا. هناك مثال على ذلك في أسلوب `__str__`. في هذا السيناريو، عندما ندعو `__str__()` سوف تحصل على نص (**string**) مع عنوان البريد. + +كما لاحظ أن كلا `def publish(self):` و `def __str__(self):` يتم فصلها داخل فئتنا. نظراً لأن بايثون حساسة للمسافة البيضاء، نحن بحاجة لوضع مسافة بادئة لأساليب عملنا داخل الفئة. بخلاف ذلك، الأساليب التي لا تنتمي إلى الفئة، ويمكنك الحصول على بعض السلوك الغير متوقع. + +إذا كان هناك شيء لا يزال غير واضح حول النماذج، لا تتردد بسؤال المدرب الخاص بك! نحن نعلم أنها معقدة، لا سيما عندما كنت تتعلم ما الأشياء والمهام في نفس الوقت. ولكن نأمل أن يبدو أقل سحرا قليلا الآن! + +### إنشاء جداول للنماذج في قاعدة البيانات الخاصة بك + +الخطوة الأخيرة هنا لإضافة نموذجنا الجديد إلى قاعدة البيانات الخاصة بنا. أولاً يجب أن تجعل جانغو يعرف أن لدينا بعض التغييرات في نموذجنا. (لقد أنشئناه للتو!) إذهب إلى إطار وحدة التحكم الخاصة بك واكتب `python manage.py makemigrations blog`. ستبدو كالشكل التالي: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**ملاحظة:** تذكر أن تقوم بحفظ الملفات التي يمكنك تحريرها. وبخلاف ذلك، سيقوم الكمبيوتر بتنفيد النسخة السابقة والتي قد تعطيك رسائل خطأ غير متوقعة. + +أعدت دجانغو ملف ترحيل لنا وعلينا الآن أن نطبقه على قاعدة البيانات الخاصة بنا. اكتب `python manage.py migrate blog` ويكون الإخراج كما يلي: + +{% filename %}command-line{% endfilename %} + + (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 + + +يا هلا! الآن لدينا نموذج آخر في قاعدة بياناتنا! سيكون من الجميل أن نراه ، اليس كذالك؟ انتقل إلى الفصل التالي لمعرفة الشكل الذي تبدو عليه مشاركتك! \ No newline at end of file diff --git a/ar/django_orm/README.md b/ar/django_orm/README.md new file mode 100644 index 00000000000..2942903611f --- /dev/null +++ b/ar/django_orm/README.md @@ -0,0 +1,218 @@ +# ORM جانغو و Querysets + +في هذا الفصل سوف تتعلم كيف تتصل جانغو بقاعدة البيانات وتقوم بتخزين البيانات فيها. دعونا نغوص في الشرح! + +## ما هو QuerySet؟ + +QuerySet هو، في جوهره، قائمة الكائنات من نموذج معين. QuerySet تسمح لك بقراءة البيانات من قاعدة البيانات، وتصفيها وتطلبها. + +من السهل التعلم عبر الأمثلة ، دعونا نجرب ذالك. هيا بنا؟ + +## Django shell + +إفتح وحدة التحكم المحلية الخاصة بك (ليس على PythonAnywhere) واكتب هذا الأمر: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +التأثير يجب أن يكون مثل: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +أنت الآن في جانغو في وحدة التحكم التفاعلية. أنها تماما مثل موجه بيثون، ولكن مع بعض سحر جانغو الإضافي. :) يمكنك استخدام كافة اوامر بيثون هنا أيضا، بطبيعة الحال. + +### كل الكائنات + +دعونا نحاول عرض جميع المشاركات لدينا أولاً. يمكنك القيام بذلك باستخدام الأمر التالي: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +اووبس! ظهر خطأ. يقول لنا أنه لا يوجد أي مشاركة. هذا صحيح لقد نسينا استيراده أولا! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +نستورد النموذج `Post` من`blog.models`. لنحاول عرض جميع المشاركات مرة أخرى: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +هذه قائمة باالمشاركات التي أنشأنا في وقت سابق! قمنا بإنشاء هذه المشاركات باستخدام واجهة المشرف جانغو. ولكن الآن نحن نريد انشاء مشاركات جديدة باستخدام بيثون، فكيف نفعل ذلك؟ + +### إنشاء كائن + +هذه هي الطريقة التي تقوم بها بإنشاء مشاركة كائن جديد في قاعدة البيانات: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +ولكن لدينا عنصر واحد في عداد المفقودين هنا `me`. نحن بحاجة إلى تمرير مثيل من نموذج `User` كمؤلف. كيف نفعل ذلك؟ + +دعونا نسترد نموذج المستخدم الأول: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +اية مستخدمين لدينا في قاعدة البيانات الخاصة بنا؟ جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +هذا هو المستخدم الخارق الذي أنشأنا في وقت سابق! دعونا نحصل على مثيل للمستخدم الآن: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +كما ترون، نحن الآن`get` ا `User` مع `username` يساوي 'ola'. أنيق! بطبيعة الحال، عليك ضبط هذا الخط لاستخدام اسم المستخدم الخاص بك. + +الآن يمكننا أخيرا إنشاء مشاركة: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +يا هلا! هل تريد التحقق من ما إذا كان يعمل؟ + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +هاهي ذا! مشاركة آخرى في القائمة! + +### إضافة المزيد من المشاركات + +يمكنك الآن الحصول على القليل من المرح وإضافة المزيد من المشاركات لنرى كيف يعمل. أضف اثنين أو ثلاثة آخرين ثم انتقل إلى الجزء التالي. + +### تصفية الكائنات + +جزء كبير من QuerySets هو القدرة على تصفيتهم. لنفترض أننا نريد العثور على جميع المشاركات التي قام المستخدم ola بتأليفها. سنقوم باستخدام `filter` بدلاً من `all` في `Post.objects.all()`. بين قوسين نوضح ما هي الشروط التدوينة تحتاج إلى تلبية في نهاية المطاف في queryset لدينا. وفي حالتنا، الشرط أن `author` يجب أن يكون متساوي مع `me`. طريقة كتابتها في دجانغو `author=me`. الأن قطعتنا من الكود تبدو بهذا الشكل: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` + +أو ربما نريد أن نرى جميع المشاركات التي تحتوي على كلمة 'title' في الحقل `title`؟ + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **ملاحظة** هناك حرفان أسفل السطر (`_`) بين `title` و `contains`. يستخدم ORM دجانغو هذه القاعدة لفصل أسماء الحقول ("title") والعمليات أو الفلاتر ("contains"). إذا قمت باستخدام تسطير واحد فقط، سوف تحصل على خطأ مثل "FieldError: Cannot resolve keyword title_contains". + +يمكنك أيضا الحصول على قائمة بجميع المشاركات المنشورة. علينا القيام بذلك بتصفية جميع المشاركات التي قد `published_date` في الماضي: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +للأسف، لم يتم نشر المشاركة التي أضفناها من وحدة تحكم بايثون بعد. ولكن يمكننا تغيير ذلك! احصل أولا على مثال لمشاركة نريد نشرها: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +ثم أنشرها باستخدام طريقة `publish`: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +الآن في محاولة للحصول على قائمة المشاركات المنشورة مرة أخرى (اضغط على مفتاح السهم لأعلى ثلاث مرات واضغط `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### العناصر الصادرة + +QuerySets تسمح لك أيضا بترتيب قائمة الكائنات. دعونا نحاول ترتيبها حسب الحقل `created_date`: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +يمكننا أيضا عكس الترتيب بإضافة `-` في البداية: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### مجموعات الاستعلام المتسلسلة + +يمكنك أيضا دمج QuerySets من خلال **chaining** معا: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +هذا حقا قوي ويتيح لك كتابة استفسارات معقدة جدا. + +رائع! أنت الآن جاهز للجزء التالي! لإغلاق الشل shell، اكتب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/ar/django_start_project/README.md b/ar/django_start_project/README.md new file mode 100644 index 00000000000..222379c217b --- /dev/null +++ b/ar/django_start_project/README.md @@ -0,0 +1,202 @@ +# مشروعك الأول في دجانغو! + +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots). +> +> جزء من هذا القسم يستند [django-marcador tutorial](http://django-marcador.keimlink.de/) المرخص لها بمرخصة بموجب المشاع الإبداعي   إسناد-على غرار 4.0 الترخيص الدولي. البرنامج التعليمي django-marcador حقوق الطبع والنشر من قبل Markus Zapke-Gründemann وآخرون. + +سنقوم بإنشاء مدونة صغيرة! + +الخطوة الأولى هي إنشاء مشروع جانغو جديد. في الأساس، وهذا يعني أننا سوف نشغل بعض البرامج النصية التي تقدمها جانغو والتي من شأنها أن تخلق الهيكل العظمي لمشروع دجانغو بالنسبة لنا. هذه مجرد حفنة من الدلائل والملفات التي سوف نستخدمها في وقت لاحق. + +أسماء بعض الملفات والدلائل مهمة جداً لجانغو. يجب عدم إعادة تسمية الملفات التي نحن على وشك إنشائها. نقلهم إلى مكان مختلف ليست فكرة جيدة. جانغو تحتاج إلى الحفاظ على بنية معينة لتكون قادرة على العثور على أشياء مهمة. + +> تذكر أن تقوم بتشغيل كل شيء في virtualenv. إذا كنت لا ترى بادئة `(myvenv)` في وحدة التحكم الخاصة بك، تحتاج إلى تنشيط virtualenv الخاص بك. قمنا بشرح طريقة فعل ذالك في **Django installation** في قسم **Working with virtualenv**. كتابة `myvenv\Scripts\activate` في وندوز ، او `source myvenv/bin/activate` في ماك ولينكس سيقوم لك بذالك. + + + +في وحدة التحكم الخاصة بك ماكنتوش أو لينكس، يجب أن تقوم بتشغيل الأمر التالي. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> الفاصلة `.` أمر بالغ الأهمية لأنه يخبر السكريبت لتثبيت دجانغو في الدليل الحالي الخاص بك (`.` الفاصلة هي إشارة قصيرة). +> +> **ملاحظة** عند كتابة الأمر أعلاه، تذكر أن تكتب فقط الجزء الذي يبدأ ب `django-admin`. الجزء `(myvenv) ~/djangogirls$` الموضح هنا هو مجرد مثال من الموجه الذي سيدعو المدخلات الخاصة بك على سطر الأوامر الخاص بك. + + + + + +في وحدة التحكم الخاصة بوندوز، يجب أن تقوم بتشغيل الأمر التالي. **Don't forget to add the period (or dot) `.` at the end!**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> الفاصلة `.` أمر بالغ الأهمية لأنه يخبر السكريبت لتثبيت دجانغو في الدليل الحالي الخاص بك (`.` الفاصلة هي إشارة قصيرة). +> +> **ملاحظة** عند كتابة الأمر أعلاه، تذكر أن تكتب فقط الجزء الذي يبدأ ب `django-admin.py`. الجزء (myvenv) C:\Users\Name\djangogirls>` الموضح هنا هو مجرد مثال من الموجه الذي سيدعو المدخلات الخاصة بك على سطر الأوامر الخاص بك. + + + +`django-admin.py` هو البرنامج النصي الذي سينشئ الدلائل والملفات بالنسبة لك. يجب أن يكون لديك الآن هيكل دليل يشبه هذا: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **ملاحظة** في بنية الدليل، سترى أيضا `venv` الذي أنشأناه من قبل. + +`manage.py` هو سكريبت يساعد في إدارة الموقع. مع أنه سوف نتمكن من (ضمن أمور أخرى) لبدء تشغيل خادم الويب على جهاز الكمبيوتر بدون تثبيت أي شيء آخر. + +يحتوي الملف `settings.py` على إعدادات موقعك. + +تذكر عندما تكلمنا عن ساعي البريد الذي يبحث اين يرمي الرسائل? `urls.py` ملف يحتوي على قائمة أنماط مستخدمة من قبل `urlresolver`. + +دعونا نتجاهل الملفات الأخرى في الوقت الراهن فنحن لن نغييرها. الشيء الوحيد الذي يجب تذكره هو عدم حذفها عن طريق الصدفة! + +## تغيير الإعدادات + +دعونا نجري بعض التغييرات في `mysite/settings.py`. قم بفتح الملف باستخدام محرر التعليمات البرمجية يالذي قمنا بتثبيته في وقت سابق. + +**ملاحظة**: ضع في اعتبارك أن `settings.py` هو ملف عادي، مثل أي ملف آخر. يمكنك فتحه من داخل محرر التعليمات البرمجية، وذلك باستخدام "ملف > فتح" قائمة الإجراأت. سيؤدي هذا بك إلى الحصول على النافذة المعتادة التي يمكنك فيها الانتقال إلى ملف `settings.py` وتحديده. بدلا من ذلك، يمكنك فتح الملف عن طريق الانتقال إلى مجلد djangogirls على سطح المكتب الخاص بك والنقر بزر الماوس الأيمن عليه. ثم، حدد محرر التعليمات البرمجية الخاصة بك من القائمة. اختيار المحرر مهم كما قد يكون لديك برامج أخرى مثبتة يمكنها فتح الملف ولكن لن تسمح لك بتحريره. + +سيكون من الجميل أن يكون الوقت صحيح على موقعنا على الانترنت. اذهب الى [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) وانسخ الوقت في منطقتك الزمنية (TZ) (e.g. `Europe/Berlin`). + +في `settings.py`، أعثر على السطر الذي يحتوي على `TIME_ZONE` وعدله لاختيار المنطقة الزمنية الخاصة بك. على سبيل المثال: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +كود لغة يتكون من لغة، مثل `en` للغة الإنكليزية أو `de` للالمانية، ورمز البلد، مثل `de` لألمانيا أو `ch` لسويسرا. سوف تحتاج إلى إضافة هذا إذا كنت تريد الأزرار الافتراضية والإخطارات من جانغو أن تكون بلغتك. لذلك سيكون لديك زر "إلغاء" ترجم إلى اللغة التي حددتها هنا. [جانغو يأتي مع الكثير من الترجمات ](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +تغيير رمز اللغة عن طريق تغيير السطر التالي: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +سوف نحتاج أيضا إلى إضافة مسار للملفات الثابتة. ( سوف نعرف كل شيء عن الملفات الثابتة والمغلقة في وقت لاحق في البرنامج التعليمي). الانتقال إلى أسفل إلى *end* الملف، وتحت `STATIC_URL`، أضف وحدة جديدة تسمى `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +عندما يكون `DEBUG` هو `True` و `ALLOWED_HOSTS فارغ، يتم التحقق من المضيف مع ['localhost', '127.0.0.1', '[::1]']`. هذا لن يطابق اسم المضيف لدينا على PythonAnywhere بمجرد نشر التطبيق لدينا لذلك سوف نقوم بتغيير الإعداد التالي: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **ملاحظة**: إذا كنت تستخدم Chromebook، أضف هذا السطر في الجزء السفلي من الملف settings.py: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> اضف ايضا `.c9users.io` الى `ALLOWED_HOSTS` اذا كنت تستخدم cloud9 + +## إعداد قاعدة البيانات + +هناك الكثير من برامج قواعد البيانات المختلفة التي يمكنها تخزين البيانات لموقعك. سنستخدم الإعداد الافتراضي، `sqlite3`. + +تم إعداد هذا بالفعل في هذا الجزء الخاص بك من الملف `mysite/settings.py`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +لإنشاء قاعدة بيانات مدونتنا، دعونا تشغل الأمر التالي في وحدة التحكم: `python manage.py migrate`(نحن بحاجة إلى أن تكون في الدليل `djangogirls` الذي يحتوي على الملف `manage.py`. اذا مر كل شيء على ما يرام، سترى شيئا مثل هذا: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +ها قد انتهينا! حان الوقت لتشغيل خادم الويب ومعرفة ما إذا كان موقعنا يعمل! + +## بدء تشغيل خادم الويب + +يجب أن تكون في الدليل الذي يحتوي على ملف `manage.py`(دليل `djangogirls`). في وحدة التحكم، يمكننا أن نبدأ خادم الويب بتشغيل `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +إذا كنت في كروم بوك، استخدم هذا الأمر بدلاً من ذلك: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +إذا كنت على ويندوز، و فشل هذا مع `UnicodeDecodeError`, ، استخدم هذا الأمر بدلاً من ذلك: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +الآن كل ما عليك القيام به هو الاختيار الذي يقوم بتشغيل موقع الويب الخاص بك. قم بفتح المتصفح (فايرفوكس، كروم، سفاري، إنترنت إكسبلورر أو مهما كنت تستخدم) وأدخل هذا العنوان: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +إذا كنت تستخدم Chromebook، عليك دائماً زيارة خادم الاختبار الخاص بك عن طريق الوصول إلى: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +تهانينا! قمت بإنشاء موقعك الأول وتشغيله باستخدام خادم الويب! أليس هذا رائع؟ + +![إنه كان مجديًا!](images/it_worked2.png) + +بينما يتم تشغيل خادم الويب، لن تشاهد موجه سطر أوامر جديدة لإدخال أوامر إضافية. لوحة التحكم تقبل نصوص جديدة ولكن لن يتم تنفيذ الأوامر الجديدة. وهذا لأن خادم الويب يعمل بشكل مستمر للاستماع للطلبات الواردة. + +> لقد استعرضنا كيف تعمل خادمات الويب في الفصل **How the Internet works**. + +لكتابة أوامر إضافية أثناء تشغيل خادم الويب، افتح نافذة طرفية جديدة وقم بتنشيط virtualenv الخاص بك. لإيقاف خادم الويب، قم بالتبديل مرة أخرى إلى النافذة التي يتم تشغيلها واضغط على CTRL+C - مفاتيح التحكم و C معا (على ويندوز، قد تضطر إلى الضغط على Ctrl+Break). + +أنت مستعد للخطوة التالية؟ لقد حان الوقت لإنشاء بعض المحتوى! \ No newline at end of file diff --git a/ar/django_templates/README.md b/ar/django_templates/README.md new file mode 100644 index 00000000000..844a153d6ba --- /dev/null +++ b/ar/django_templates/README.md @@ -0,0 +1,106 @@ +# قوالب دجانغو + +حان الوقت لكي نظهر بعض المعلومات! جانغو يعطينا بعضا من شعارات القوالب المفيدة المثبتة فية. + +## ما هي شعارات القوالب؟ + +كما تعرف في لغة الHTML لا يمكنك كتابة كود مكتوب بلغة Python وذلك لأن متصفحات الانترنت لا تفهمة. المتصفحات تفهم الHTML فقط. نحن نعلم أن الHTML نوعا ما جامدة لكن الPython أكثر ديناميكية. + +**Django template tags** تسمح لنا بنقل أشياء مثل بيثون إلى HTML، حتى نتمكن من بناء مواقع ديناميكية بشكل أسرع. رائع! + +## عرض قالب قائمة المشاركات + +في الفصل السابق، قدمنا لقالبنا قائمة بالمشاركات في متغير `posts`. الآن سوف نقوم بعرضه في HTML. + +لطباعة متغير في قوالب جانغو، نحن نستخدم أقواس مزدوجة مع اسم المتغير في الداخل، هكذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +جرب هذا في قالبك `blog/templates/blog/post_list.html`. استبدل كل شيء من `
` الثاني الى `
` الثالت ب `{{ posts }}`. قم بحفظ الملف، وقم بتحديث الصفحة لمشاهدة النتائج: + +![الرقم 13.1](images/step1.png) + +كما ترون، كل ما لدينا هو هذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +هذا يعني أن جانغو يفهم ذلك كقائمة من الكائنات. هل تتذكر من **Introduction to Python** كيف نضهر القوائم؟ نعم، مع حلقات! في قالب جانغو يمكنك القيام بها هكذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +جرب هذا في قالبك. + +![الرقم 13.2](images/step2.png) + +إنه كان مجديًا! ولكننا نريد أن يتم عرض المشاركات مثل المشاركات الثابتة التي أنشأناها سابقا في فصل **مقدمة إلى HTML**. يمكنك خلط علامات HTML والقالب. `body` سيبدو هكذا: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %} كل شيء تضعه بين `{% for %}` و `{% endfor %}` سوف يتكرر لكل كائن في القائمة. حدث الصفحة:{% endraw %} + +![الرقم 13.3](images/step3.png) + +هل لاحظت أننا استخدمنا تدوين مختلف قليلا هذه المرة (`{{ post.title }}` او `{{ post.text }})`؟ يمكننا الوصول إلى البيانات في كل حقل من الحقول المعرفة في نموذج `Post`. ايضا `|linebreaksbr` يربط نص المشاركات من خلال مرشح لتحويل فواصل الأسطر إلى فقرات. + +## شيء واحد آخر + +سيكون جيدا معرفة ما إذا كان موقع الويب الخاص بك لا يزال يعمل على شبكة الإنترنت العامة، اليس كذالك؟ دعونا نحاول نشره في PythonAnywhere مرة أخرى. هنا خلاصة للخطوات… + +* أولاً، ادفع التعليمات البرمجية الخاصة بك إلى Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* افتح [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) واذهب الى **Bash console** او افتح واحدة جديدة وشغل هذا الأمر: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* وأخيرا، انتقل إلى علامة التبويب [Web tab](https://www.pythonanywhere.com/web_app_setup/) واضغط على **Reload**. على تطبيق الويب. يجب أن يكون التحديث مباشر! إذا كانت مشاركات المدونة على موقع PythonAnywhere لا تتطابق مع المشاركات التي تظهر على المدونة المستضافة على الخادم المحلي، فلا بأس بذالك. قواعد البيانات على جهاز الكمبيوتر المحلي وبايثون في أي مكان لا يتزامنان مع بقية الملفات الخاصة بك. + +مبروك! الآن امضي قدما وحاول إضافة مشاركة جديدة عبر إدارة جانغو الخاصة بك (تذكر لإضافة publication_date!) تأكد من أنك في إدارة جانغو لموقع pythonanywhere الخاص بك، https://yourname.pythonanywhere.com/admin. ثم حدث الصفحة لمعرفة ما إذا كانت المشاركة تظهر هناك أم لا. + +تعمل كالحصان ! نحن فخورون بك ، ابتعد قليلا عن الحاسوب الخاص بك ، انت تستحق استراحة + +![الرقم 13.4](images/donut.png) \ No newline at end of file diff --git a/ar/django_urls/README.md b/ar/django_urls/README.md new file mode 100644 index 00000000000..b26e948e011 --- /dev/null +++ b/ar/django_urls/README.md @@ -0,0 +1,129 @@ +# روابط دجانغو + +نحن على وشك بناء صفحتنا الأولى على الأنترنت: الصفحة الرئيسية لمدونتك! ولكن أولاً، دعونا نتعلم قليلاً عن "روابط مواقع جانغو". + +## ما هو عنوان URL؟ + +ببساطة URL هو عنوان ويب. يمكنك أن ترى عنوان URL في كل مرة تقوم بزيارة موقع على شبكة الإنترنت--أنها مرئية في شريط العناوين في المتصفح الخاص بك. (نعم! `127.0.0.1:8000` هو عنوان URL! و `https://djangogirls.org` أيضا عنوان URL) + +![عنوان Url](images/url.png) + +كل صفحة على شبكة الإنترنت تحتاج إلى عنوان URL الخاص بها. وبهذه الطريقة التطبيق الخاص بك يعلم ما يجب أن يظهر للمستخدم الذي يقوم بفتح عنوان URL هذا. في جانغو نستخدم ما يسمى `URLconf` (URL configuration). URLconf هو مجموعة من الأنماط التي ستحاول جانغو مطابقتها مع عنوان URL المطلوب للعثور على طريقة العرض الصحيح. + +## كيف تعمل عناوين Url في جانغو؟ + +دعونا نفتح الملف `mysite/urls.py` في محرر التعليمات البرمجية الخاصة بك للاختيار ونرى ما يبدو عليه: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +كما ترون، جانغو قد وضعت بالفعل شيء هنا بالنسبة لنا. + +الخطوط بين علامات الاقتباس الثلاثي (`'' '` أو `"""`) تسمى docstrings – ييمكنك كتابتها في أعلى ملف أو فئة أو طريقة لوصف ما يفعله. هي لا تعمل عبر بايثون. + +عنوان URL المشرف، الذي زرته في الفصل السابق، موجود هنا: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +هذا السطر يعني أن لكل عنوان URL الذي يبدأ ب `admin/`، سوف تجد جانغو مقابله *view*. في هذه الحالة نحن ، نضع الكثير من روابط المشرفين ، لذالك هي ليست مجموعة كلها في هذا الملف الصغير ، انها اكثر قابلية للقراءة وانضف. + +## Regex + +هل كنت تتساءل كيف تطابق جانغو عناوين Url للواجهات ؟ حسنا، هذا الجزء صعب. يستخدم جانغو `regex`، اختصار ل "التعبيرات العادية". Regex لديه الكثير (الكثير!) من القواعد التي تشكل نمط بحث. بما ان regexes موضوع متقدم، نحن لن تمر بالتفصيل على كيفية عمله. + +إذا كنت لا تزال ترغب معرفة كيف قمنا بإنشاء الأنماط، هنا مثال للعملية – سوف نحتاج فقط مجموعة فرعية محدودة من القواعد للتعبير عن النمط الذي نتطلع اليه وهي: + +* `^` في بداية النص +* `$` في نهاية النص +* `\d` لرقم +* `+` للإشارة إلى أن العنصر السابق ينبغي أن يتكرر مرة واحدة على الأقل +* `()` لالتقاط جزء من النمط + +أي شيء آخر في تعريف عنوان URL سوف تؤخذ حرفيا. + +الآن تخيل أن لديك موقع على شبكة الإنترنت بعنوان مثل `http://www.mysite.com/post/12345/`، حيث يكون `12345` هو عدد مشاركاتك. + +كتابة آراء منفصلة لجميع أرقام المشاركات سيكون مزعج حقاً. مع التعابير العادية، يمكننا إنشاء الأنماط التي تتطابق مع عنوان URL واستخراج العدد لنا: `^ post/(\d+)/$`. دعونا نكسر هذا قطعة قطعة لمعرفة ما نقوم به هنا: + +* **^post/** تخبر دجانغو عن اتخاذ أي شيء يحتوي على `post/` في بداية عنوان url (مباشرة بعد `^`) +* **(\d+)** يعني أنه سيكون هناك عدد (رقم واحد أو أكثر)، وأننا نريد الرقم الذي تم التقاطه واستخراجه +* **/** يخبر دجانغو أن حرف آخر `/` يجب أن يتبع +* **$** يشير إلى نهاية عنوان url الخاص بمعنى أن السلاسل التي تنتهي مع `/` سوف تتطابق مع هذا النمط + +## عنوان URL جانغو الأول! + +حان الوقت لإنشاء URL الأول لدينا! ونحن نريد 'http://127.0.0.1:8000/' لتكون الصفحة الرئيسية لمدونتنا وتعرض قائمة من المشاركات. + +نريد أيضا الاحتفاظ بالملف `mysite/urls.py` نظيف، حيث أننا سوف نسترد عناوين Url من تطبيق `blog` لدينا إلى الملف الرئيسي `mysite/urls.py`. + +امضي قدما ،واضع هذا السطر الذي سيسترد `blog.urls`.. لاحظ أننا نستخدم الدالة `include` هنا، لذا ستحتاج إلى إضافة هذا الاستيراد. + +الآن يجب أن تبدو الملف `mysite/urls.py` الخاص بك مثل هذا: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +جانغو سيقوم بإعادة توجيه كل شيء يأتي في 'http://127.0.0.1:8000/' إلى`blog.urls` والبحث عن مزيد من التعليمات هناك. + +يتم كتابة التعبيرات العادية في بايثون دائماً مع `r` أمام السلسلة. هذا تلميح مفيد لبايثون أن السلسلة قد تحتوي على الأحرف الخاصة التي ليست معنية ببايثون نفسه، ولكن للتعبير العادي بدلاً من ذلك. + +## روابط المدونة + +قم بإنشاء ملف فارغ جديد يسمى `urls.py` في الدليل `blog`. حسنًا! أضف هذه الأسطر الأولى والثانية: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +نحن هنا نستورد وضائف دجانغو `url` وجميع `views` من تطبيق `blog` (ليس لدينا أي حتى الآن، ولكننا سوف نحصل على ذلك في دقيقة واحدة) + +بعد ذلك، يمكننا أن نضيف لدينا نمط URL الأول: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +كما ترون، نحن الآن تعيين طريقة `عرض` تسمى `post_list` `^ $` لعنوان URL. هذا التعبير العادي وسيطابق `^` (بداية) تليها `$` (نهاية) – لذلك سلسلة فارغة فقط سوف تتطابق. وهذا صحيح، لأن في URL جانغو resolvers، 'http://127.0.0.1:8000/' ليست جزءا من عنوان URL. سيعلم هذا النمط دجانغو أن `views.post_list` هو المكان المناسب للذهاب إليه إذا دخل شخص ما موقعك على الويب على العنوان "http://127.0.0.1:8000/". + +الجزء الأخير، `name='post_list'`, هو اسم عنوان URL الذي سيتم استخدامه لتحديد طريقة العرض. وهذا يمكن أن يكون نفس اسم العرض ولكن أيضا يمكن أن يكون شيئا مختلفاً تماما. سنستخدم عناوين URLs المسماة لاحقا في المشروع، لذلك من المهم تسمية كل عنوان URL في التطبيق. يجب أن نحاول أيضا الحفاظ على أسماء عناوين URL فريدة وسهلة التذكر. + +إذا حاولت زيارة http://127.0.0.1:8000/ الآن، ستجد نوعا من رسائل الخطأ "صفحة ويب غير متوفرة". وذلك لأن الخادم (تذكر كتابة `runserver`?) لم يعد قيد التشغيل. ألق نظرة على نافذة وحدة تحكم الخادم لمعرفة السبب. + +![خطأ](images/error1.png) + +تعرض وحدة التحكم الخاصة بك خطأ، ولكن لا تقلق - إنها مفيدة حقا: إنها تخبرك بوجود **no attribute 'post_list'**. هذا هو اسم *view* الذي تحاول جانغو العثور عليه واستخدامه، ولكن لم نقم بإنشاءه بعد. في هذه المرحلة، لن يعمل `/admin/` أيضا. لا تقلق – سوف نصل إلى هناك. + +> إعرف المزيد حول URLconfs من خلال قراءة الوثائق الرسمية: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/ar/django_views/README.md b/ar/django_views/README.md new file mode 100644 index 00000000000..40910a5905e --- /dev/null +++ b/ar/django_views/README.md @@ -0,0 +1,43 @@ +# وجهات نظر جانغو -وقت الإنشاء! + +حان الوقت للتخلص من الشوائب التي انشأناها في الفصل الأخير! :) + +*view* هو المكان الذي وضعنا فيه المنطق الخاص بتطبيقنا. وسوف تطلب معلومات من `model` قمت بإنشائها من قبل وتمريرها إلى `template`. سوف ننشئ قالب في الفصل التالي. وجهات النظر هي مجرد وظائف بيثون والتي هي اكثر تعقيد قليلا من التي قمنا بكتابتها في هذا الفصل **مقدمة بيثون**. + +Views توضع في الملف `views.py`. وسوف نضيف *views* الخاصة بنا الى `blog/views.py`. + +## blog/views.py + +حسنا، دعونا نفتح هذا الملف، ونرى ما هو في موجود: + +{% filename %}blog/views.py{% endfilename %} + +```python +من django.shortcuts استرد المحول +إنشاء طرق العرض الخاصة بك هنا. +``` + +ليس هناك كثيرا من الأشياء هنا حتى الآن. + +تدكر ان الأسطر التي تبدأ ب`#` هي مجرد تعليقات وهذا يعني انها لن يتم استخدامها عبر بايثون. + +دعونا ننشء *view * كما يوحي التعليق. أضف الأسطر التالية أدناه: + +{% filename %}blog/views.py{% endfilename %} + +```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/وانظر ماذا لدينا. + +خطأ آخر! اقرأ ما يجري الآن: + +![خطأ](images/error.png) + +هذا يبين أن الملقم قيد التشغيل مرة أخرى، على الأقل، ولكن لا يزال يبدو وكأنه ليس على ما يرام أليس كذالك؟ لا تقلق، انها مجرد صفحة خطأ، لا تخف! تماما مثل رسائل الخطأ في وحدة التحكم، هذه في الواقع مفيدة جدا. يمكن أن تقرأ أن*TemplateDoesNotExist*. دعونا نصلح هذا الخطأ وننشئ قالب في الفصل التالي! + +> إعرف المزيد حول آراء جانغو من خلال قراءة الوثائق الرسمية: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/ar/dynamic_data_in_templates/README.md b/ar/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..807bb666ebc --- /dev/null +++ b/ar/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/ar/extend_your_application/README.md b/ar/extend_your_application/README.md new file mode 100644 index 00000000000..9ee70d41a57 --- /dev/null +++ b/ar/extend_your_application/README.md @@ -0,0 +1,197 @@ +# توسيع التطبيق الخاص بك + +لقد أنجزنا فعلا جميع الخطوات المختلفة اللازمة لإنشاء موقعنا على الإنترنت: نحن نعرف كيفية كتابة نموذج، url وطريقة العرض والقالب. نحن نعلم أيضا كيفية جعل موقع الويب الخاص بنا جميلا. + +حان الوقت للتدريب! + +أول شيء نحتاجه في مدونتنا هو، على الأرجح، صفحة لعرض مشاركة واحدة، أليس كذلك؟ + +لدينا بالفعل نموذج `Post` ، حتى لا تحتاج إلى إضافة أي شيء إلى `models.py`. + +## إنشاء رابط نموذج لتفاصيل المشاركة + +سوف نبدأ بإضافة رابط داخل الملف `blog/templates/blog/post_list.html`. حتى الآن ينبغي له ان يبدو هكذا:{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %} نريد الحصول على رابط من عنوان المشاركة في قائمة المشاركات إلى صفحة تفاصيل المشاركة. دعونا نغيير `

{{ post.title }}

` بحيث يرتبط بصفحة تفاصيل المشاركة :{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %} حان الوقت لشرح `{% url 'post_detail' pk=post.pk %}`. كما قد تضن، فإن `{% %}` يعني أننا نستخدم علامات قالب جانغو. هذه المرة سوف نستخدم واحد واحد منهم والذي سيقوم بإنشاء عنوان URL لنا!{% endraw %} + +`post_detail` يعني أن جانغو سيتوقع عنوان URL في `blog/urls.py` ب name=post_detail + +وماذا عن `pk=post.pk`؟ `pk` هو اختصار للمفتاح الأساسي، وهو اسم فريد لكل سجل في قاعدة البيانات. ونظرا لأننا لم نحدد مفتاحا أساسيا في نموذج `Post`، فإن دجانغو ينشئ واحدا لنا (بشكل افتراضي، وهو رقم يزيد بمقدار واحد لكل سجل، أي 1 و 2 و 3) ويضيفه كحقل يدعى`pk` إلى كل من مشاركاتنا. نصل إلى المفتاح الأساسي من خلال كتابة `post.pk`,، بنفس الطريقة التي نصل بها إلى الحقول الأخرى (`title`, `author`, etc.) في `Post`! + +الآن عندما ننتقل إلى http://127.0.0.1:8000/ سيكون لدينا خطأ (كما هو متوقع، نظرا لأنه لا يوجد لدينا عنوان URL أو *view* ل `post_detail`). وسوف تبدو كما يلي: + +![خطأ NoReverseMatch](images/no_reverse_match2.png) + +## إنشاء عنوان URL لتفاصيل المشاركة + +لنقم بإنشاء عنوان URL في `urls.py` من اجل `post_detail` *view*! + +نريد عرض تفاصيل المشاركة الأولى على هذا العنوان **URL**: http://127.0.0.1:8000/post/1/ + +دعونا ننشئ عنوان URL في ملف `blog/urls.py` لتوجيه دجانغو إلى *view* باسم `post_detail`,، سيتم عرض إحدى المشاركات بأكملها. أضف السطر `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` إلى الملف `blog/urls.py`. الآن يجب أن يبدو الملف الخاص بك مثل هذا: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +هذا الجزء `^post/(?P\d+)/$` يبدو مخيفا، ولكن لا تقلق – سوف نشرح لك: + +- أنه يبدأ ب `^` مرة أخرى – "البداية". +- `post/` يعني فقط أنه بعد البداية، يجب أن يحتوي عنوان URL على كلمة **post** و **/**. حتى الان جيد جدا. +- `(?P\d+)` -هذا الجزء أصعب. وهذا يعني أن جانغو سوف تأخذ كل ما تضعه هنا وتنقله إلى عرض كمتغير يسمى `pk`. (لاحظ أن هذا يطابق الاسم الذي قدمناه لمتغير المفتاح الأساسي مرة أخرى في `blog/templates/blog/post_list.html`!) `\d` يخبرنا أيضا أنه يمكن أن يكون فقط رقم، وليس حرف ( كل شيء بين 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/` في المتصفح، جانغو ستفهم انك تبحث عن *view* تسمى `post_detail` ونقل معلومة أن `pk` تساوي `5` إلى ذالك *view*. + +حسنا، لقد أضفنا نمط عنوان URL جديد إلى `blog/urls.py`! دعونا نقم بتحديث الصفحة http://127.0.0.1:8000/ بوم! توقف الخادم عن العمل مرة أخرى. ألقي نظرة على وحدة التحكم – كما هو متوقع، هناك خطأ آخر! + +![AttributeError](images/attribute_error2.png) + +هل تذكر ما الخطوة التالية؟ بطبيعة الحال: إضافة طريقة عرض! + +## إضافة مشاركة لعرض التفاصيل + +هذه المرة لدينا *view* تعطي معلمة إضافية، `pk`. *view* تحتاج الى القبض عليه ، اليس كذالك؟ لذا فإننا سوف نحدد وظيفتنا ك `def post_detail(request, pk):`. لاحظ أننا بحاجة إلى استخدام نفس الاسم بالضبط الذي حددناه في عناوين urls (`pk`). حذف هذا المتغير غير صحيح وسوف ينتج خطأ! + +الآن، نريد الحصول على مشاركة مدونة واحدة فقط. لإجراء ذلك، يمكننا استخدام مجموعة طلبات بحث، كما يلي: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +ولكن توجد مشكلة في التعليمات البرمجية هذه. إذا لم يكن هناك `Post` بعينها `primary key` (`pk`) سيكون لدينا خطأ سوبر قبيح! + +![خطأ DoesNotExist](images/does_not_exist2.png) + +نحن لا نريد ذلك! ولكن، بطبيعة الحال، جانغو تأتي بشيء أنها ستعالج ذلك لنا:: `get_object_or_404`. في حالة عدم وجود `Post` مع `pk`,، سيعرض صفحة أجمل بكثير، صفحة `Page Not Found 404`. + +![الصفحة غير موجودة](images/404_2.png) + +والخبر السار هو أنه يمكنك فعلا إنشاء صفحة `Page not found` الخاصة بك وجعلها جميلة كما تريد. لكنها ليست مهمة الأن ، لذالك سوف نتخطاها. + +طيب، حان الوقت لإضافة *view* لملف `views.py` لدينا! + +في `blog/urls.py` أنشأنا قاعدة عنوانURL اسمها `post_detail` تشير إلى ملف شخصي يسمى `views.post_detail`. وهذا يعني أن جانغو تتوقع عرض دالة تسمى `post_detail` داخل `blog/views.py`. + +ينبغي أن نفتح `blog/views.py` وإضافة التعليمة البرمجية التالية بالقرب `from` من الخطوط الأخرى: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +وفي نهاية الملف سوف نقوم بإضافة *view*: + +{% filename %}blog/views.py{% endfilename %} + +```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/ + +![عرض قائمة المشاركات](images/post_list2.png) + +إنه كان مجديًا! ولكن ماذا يحدث عندما تقوم بالنقر فوق رابط في عنوان احدى المشاركات على المدونة؟ + +![خطأ TemplateDoesNotExist](images/template_does_not_exist2.png) + +أوه لا! خطأ آخر! ولكن نحن نعلم بالفعل كيفية التعامل معه، اليس كذالك؟ نحن بحاجة لإضافة قالب! + +## إنشاء قالب لتفاصيل المشاركة + +سننشئ ملفا في `blog/templates/blog` يسمى `post_detail.html`. + +ستبدو كالشكل التالي: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +    
+        {% if post.published_date %} +            
+                {{ post.published_date }} +            
+        {% endif %} +        

{{ post.title }}

+        

{{ post.text|linebreaksbr }}

+    
+{% endblock %} +``` + +مرة أخرى نحن نوسع `base.html`. في الكتلة `content` نريد عرض تاريخ نشر المشاركة (إذا كان موجودا) والعنوان والنص. ولكن يجب أن نناقش بعض الأمور الهامة، اليس كذالك؟ + +إذا... {% raw %} `{%... %} ... {% endif %}` هو علامة قالب يمكن أن نستخدمها عندما نريد أن تحقق شيئا. (تذكر `إذا... ايضا. ` من فصل **Introduction to Python** ؟) في هذا السيناريو، نريد التحقق مما إذا كان `published_date` غير فارغ. {% endraw %} + +حسنا، يمكننا تحديث الصفحة ومعرفة ما إذا كان `TemplateDoesNotExist` قد انتهى الآن. + +![صفحة تفاصيل المشاركة](images/post_detail2.png) + +ياي! إنه يعمل! + +## شيء اخر: أنشر الوقت! + +سيكون من الجيد معرفة ما إذا كان موقع الويب الخاص بك لا يزال يعمل على PythonAnywhere، أليس كذلك؟ دعونا نحاول النشر مرة أخرى. + +{% filename %}command-line{% endfilename %} + + $ 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](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +وأخيرا، انتقل إلى علامة التبويب [Web tab](https://www.pythonanywhere.com/web_app_setup/) واضغط على **Reload**. + +هذا ينبغي ان يكون كل شيء! مبروك:) \ No newline at end of file diff --git a/ar/how_the_internet_works/README.md b/ar/how_the_internet_works/README.md new file mode 100644 index 00000000000..ac559adb2e6 --- /dev/null +++ b/ar/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# كيف تعمل الإنترنت + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc). +> +> هذا الفصل مستوحى من حديث "كيف تعمل شبكة الإنترنت" جيسيكا مك كيلار (http://web.mit.edu/jesstess/www/). + +نحن نراهن انك تستخدم الأنترنت كل يوم. ولكن هل تعرف فعلا ما يحدث عند كتابة عنوان مثل https://djangogirls.org في متصفحك والضغط على `enter`؟ + +اول شيء يجب ان تعرفه هو ان المواقع هي مجرد مجموعة من الملفات محفوضة في اقراص تخزين صلبة. تماما مثل الأفلام، والموسيقى، أو الصور. ومع ذلك، هناك جزء واحد فريد للمواقع: وهي تعليمات كمبيوتر برمجية تسمى HTML. + +إذا كنت لا تعرف البرمجة فإنه سيكون من الصعب فهم HTML في البداية، ولكن متصفحات الويب الخاص بك (مثل كروم، سفاري، فايرفوكس، الخ) تحبها. تم تصميم متصفحات الويب لفهم هذا الكود، اتباع التعليمات الخاصة به، وتقديم هذه الملفات التي تشكل موقع الويب الخاص بك، بالطريقة التي تريدها. + +كما هو الحال مع كل ملف، نحن بحاجة إلى تخزين ملفات HTML في مكان ما على قرص الثابت. بالنسبة إلى الإنترنت، نستخدم أجهزة كمبيوتر خاصة وقوية تسمى *خوادم*. أنهم لا يملكون شاشة أو ماوس أو لوحة مفاتيح، لأن الغرض الرئيسي منها هو لتخزين البيانات وخدمتها. لذالك يسمون *servers* لأنهم *serve* خدم ينقلون بياناتك. + +حسنا! لكنك تريد ان ترى كيف تعمل الأنترنت أليس كذالك؟ + +لقد رسمنا لك صورة ، ستبدو هكذا: + +![الرقم 1.1](images/internet_1.png) + +تبدو كفوضى ، اليس كذالك؟ في الواقع هي شبكة أجهزة متصلة (*ملقمات* المشار إليها أعلاه). مئات الآلاف من آلات! كيلومترات عديدة من الكابلات حول العالم! يمكنك زيارة موقع "خريطة غواصات الكابلات" (http://submarinecablemap.com) لمعرفة مدى تعقيد الشبكة. هنا لقطة شاشة من الموقع: + +![الرقم 1.2](images/internet_3.png) + +أنها رائعة، أليس كذلك؟ ولكن من الواضح أنه من غير الممكن أن يكون هناك سلك بين كل جهاز متصل بالإنترنت. إذا ، للوصول إلى جهاز (على سبيل المثال، حيث يتم حفظ https://djangogirls.org) نحن بحاجة لتمرير طلب من خلال آلات مختلفة كثيرة. + +ستبدو كالشكل التالي: + +![الرقم 1.3](images/internet_2.png) + +تخيل عند كتابة https://djangogirls.org، يمكنك إرسال رسالة تقول: "عزيزي جانغو الفتيات، أريد أن أرى الموقع djangogirls.org. أرسله لي، رجاء! " + +رسالتك تذهب إلى مكتب البريد الأقرب إليك. ثم تذهب إلى آخر أقرب قليلا إلى المرسل إليه، ثم إلى آخر، وآخر حتى يتم تسليمها إلى وجهتها. الشيء الفريد هنا إذا قمت بإرسال العديد من الرسائل (*حزم البيانات*) إلى نفس المكان، يمكن أن تذهب من خلال مكاتب بريد مختلفة تماما (*أجهزة التوجيه*). وهذا يعتمد على كيفية التوزيع في كل مكتب. + +![الرقم 1.4](images/internet_4.png) + +هذه هي طريقة عملها يمكنك إرسال الرسائل وتتوقع بعض الاستجابة. وبطبيعة الحال، بدلا من الورق والقلم يتم استخدام بيتات من البيانات، ولكن الفكرة هي نفسها! + +بدلاً من عناوين مع اسم الشارع، والمدينة، والرمز البريدي واسم البلد، نحن نستخدم عناوين IP. يسأل الكمبيوتر أولاً DNS (نظام اسم المجال) لترجمة djangogirls.org إلى عنوان IP. وهي تعمل قليلا مثل كتب الهاتف القديمة حيث يمكنك البحث عن اسم الشخص الذي تريد الاتصال به والعثور على رقم الهاتف وعنوانه. + +عندما تقوم بإرسال رسالة، فإنها تحتاج إلى بعض الميزات لتسليمها بشكل صحيح: عنوان، ختم، إلخ. انت ايضا تستخدم لغة يفهمها المتلقي، اليس كذالك؟ وينطبق نفس الشيء على *حزم البيانات* انت ترسل لترى موقع انترنت. نحن نستخدم بروتوكول يسمى HTTP (بروتوكول نقل النص التشعبي). + +لذلك، أساسا، عندما يكون لديك موقع على شبكة الإنترنت، تحتاج إلى يكون لديك *ملقم* (آلة) حيث يعيش. عندما يستلم *الملقم* *طلب* وارد (في رسالة)، يرسل إلى موقع الويب الخاص بك (في رسالة أخرى). + +بما ان هذا برنامج تعليمي لدجانغو ، قد تسأل ماذا يفعل دجانغو. عندما تقوم بإرسال استجابة، لا تريد دائماً إرسال نفس الشيء للجميع. من الأفضل بكثير ان تكون احرفك مشخصة، وخاصة للشخص الذي كتب للتو لك، أليس كذلك؟ جانغو يساعدك في إنشاء هذه الرسائل الشخصية، والمثيرة للاهتمام. :) + +يكفي الحديث--وقت البناء! \ No newline at end of file diff --git a/ar/html/README.md b/ar/html/README.md new file mode 100644 index 00000000000..1acea5b2f72 --- /dev/null +++ b/ar/html/README.md @@ -0,0 +1,213 @@ +# مقدمة إلى HTML + +قد تسأل ما هو القالب؟ + +القالب هو ملف يمكننا إعادة استخدامه لتقديم معلومات مختلفة بتنسيق ثابت - على سبيل المثال، يمكنك استخدام قالب لمساعدتك على كتابة حرف، لأنه على الرغم من أن كل حرف قد يحتوي على رسالة مختلفة ويتم توجيهها إلى شخص مختلف ، وسوف تشترك في نفس الشكل. + +تم وصف تنسيق قالب جانغو في لغة تسمى HTML (وهذا هو ال HTML التي ذكرناها في الفصل الأول،**How the Internet works**). + +## ما هي HTML؟ + +HTML هو رمز يتم تفسيره بواسطة متصفح الويب - مثل كروم أو فايرفوكس أو سفاري - لعرض صفحة ويب للمستخدم. + +نقصد ب HTML "HyperText Markup Language". **HyperText** هو نص يعتمد على الإرتباطات التشعبية بين الصفحات. **Markup** يعني أننا اتخذنا وثيقة ووضعنا علامة عليها مع رمز لنقول ل (في هذه الحالة، متصفح) كيفية تفسير الصفحة. تم إنشاء شفرة HTML باستخدام علامات **tags**، حيث يبدأ كل منها باستخدام `<` وينتهي ب `>`. تمثل هذه العلامات علامات **elements**. + +## قالبك الأول! + +إنشاء قالب يعني إنشاء ملف قالب. كل شيء هو ملف، هو؟ ربما كنت قد لاحظت هذا بالفعل. + +يتم حفظ قوالب في `blog/templates/blog` الدليل. لذا أولاً أنشئ دليل يسمى `templates` داخل دليل المدونة الخاص بك. قم بإنشاء دليل آخر يسمى `blog` داخل دليل القوالب الخاصة بك: + + blog + └───templates + └───blog + + +(قد تتساءل لماذا نحتاج إلى دليلي `blog` - كما سوف تكتشف في وقت لاحق، وهذا هو مجرد تسمية اصطلاح مفيدة تجعل الحياة أسهل عندما تبدأ الأمور أكثر تعقيدا) + +والآن قم بإنشاء ملف `post_list.html` (فقط اتركه فارغاً للآن) داخل دليل `blog/templates/blog`. + +انظر كيف يبدو موقع الويب الخاص بك الآن: http://127.0.0.1:8000/ + +> إذا كان لا يزال لديك خطأ `TemplateDoesNotExist`,، حاول إعادة تشغيل الخادم الخاص بك. انتقل الى سطر الأوامر حاول ايقاف الخادم عبر (بالضغط على Ctrl+C - مفتاح التحكم و C معا) وإعادة تشغيله من خلال تشغيل الأمر ` python manage.py runserver .

+ + +

الرقم 11.1

+ +

لا يوجد خطأ بعد الآن! تهاني:) ومع ذلك، موقع الويب الخاص بك لم ينشر أي شيء ما عدا صفحة فارغة، نظراً لأن القالب فارغ . نحن بحاجة إلى إصلاح ذلك.

+ +

أضف ما يلي إلى ملف القالب الخاص بك:

+ +

{% filename %}blog/templates/blog/post_list.html{% endfilename %}

+ +

+    

Hi there!

+

It works!

+ +`
+> +> كيف يبدو موقعك الآن؟ يرجى زيارة الموقع لمعرفة ذالك: http://127.0.0.1:8000/ +> +> ![الرقم 11.2](images/step3.png) +> +> إنه كان مجديًا! لقد قمت بعمل جيد هناك:) +> +> * إن العلامة الأساسية، ``، هي دائما بداية أي صفحة ويب و `` هي دائما النهاية. كما ترون، يذهب كامل محتوى الموقع بين بداية الوسم ``وعلامة إغلاق `` +> * `

`علامة لعناصر الفقرة؛ `

` يغلق كل فقرة +> +> ## الرأس والجسم +> +> كل صفحة HTML تنقسم إلى عنصرين هما **head** و **body**. +> +> * **head** هو عنصر يحتوي على معلومات حول المستند الذي لا يتم عرضه على الشاشة. +> +> * **body** هو عنصر يحتوي على كل شيء يتم عرضه كجزء من صفحة ويب. +> +> نحن نستخدم `` لإخبار المتصفح عن إعدادات الصفحة، و `` ليقول ما هو موجود فعلا في الصفحة. +> +> على سبيل المثال، يمكنك وضع عنصر عنوان صفحة ويب داخل ``، مثل هذا: +> +> {% filename %}blog/templates/blog/post_list.html{% endfilename %} +> +> ```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +قم بحفظ الملف وقم بتحديث الصفحة الخاصة بك. + +![الرقم 11.3](images/step4.png) + +لاحظ كيف أن المستعرض قد فهم أن "Ola's blog" هو عنوان الصفحة الخاصة بك؟ لقد فسرت `Ola's blog` ووضعت النص في شريط عنوان المتصفح (سيتم استخدامه أيضا للإشارات المرجعية وما إلى ذلك). + +ربما كنت قد لاحظت أيضا أن كل علامة افتتاح تقابلها *closing tag* مع `/` وذالك العنصر هو *nested* (بمعنى أنه لا يمكنك إغلاق علامة معينة حتى يتم إغلاق كل العلامات الموجودة داخلها). + +أنها مثل وضع الأمور في صناديق. لديك صندوق واحد كبيرة ، ``؛ يوجد داخله ``، والذي يحتوي على صناديق صغيرة `

`. + +تحتاج إلى اتباع قواعد *الإغلاق* هذه ، و *تداخل* العناصر – إذا لم تقم بذالك، المستعرض قد لا يكون قادراً على تفسيرها بشكل صحيح وسيتم عرض الصفحة الخاصة بك بشكل غير صحيح. + +## تخصيص القالب الخاص بك + +يمكنك الآن الحصول الأن على بعض المتعة ومحاولة تخصيص القالب الخاص بك! وإليك بعض العلامات المفيدة لذلك: + +* `

A heading

` لأهم عنوان لديك +* `

A sub-heading

` لعنوان في المستوى التالي +* `

A sub-sub-heading

` ومع ذالك إلى `
` +* `

فقرة من النص

` +* ويؤكد `text` على النص الخاص بك +* ويؤكد `text` بشدة على النص الخاص بك +* `
`يذهب إلى سطر آخر (لا يمكنك وضع أي شيء داخل br وليس هناك أي علامة إغلاق) +* `link` إنشاء رابط +* `
  • first item
  • second item
` أنشئ قائمة مثل هذه! +* `
` تعرف جزء من الصفحة + +هنا مثال لقالب كامل انسخه والصقه `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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](images/step6.png) + +يااي! ولكن حتى الآن، يعرض نموذجنا تماما **نفس المعلومات** - بينما كنا نتحدث عن النماذج في وقت سابق للسماح لنا بعرض معلومات ** مختلفة ** في **نفس التنسيق**. + +ما كنا نريد فعله حقا هو اضهار مشاركات حقيقية في ادارة دجانغو ، وذالك اين سنذهب لاحقا ،. + +## شيء اخر: أنشر الوقت! + +سيكون من الجيد أن نرى كل هذا على الإنترنت، ايس كذالك؟ دعونا ننشر بايثون في كل مكان اخر: + +### التزم وادفع التعليمات البرمجية الخاصة بك الى Github + +أولاً، دعونا نرى ما هي الملفات التي تغيرت منذ آخر نشر (شغل هذه الأوامر محليا ، ليس في بايثون في كل مكان): + +{% filename %}command-line{% endfilename %} + + $ git status + + +تأكد من أنك في دليل `djangogirls` ودعنا نخبر `git` بتضمين جميع التغييرات ضمن هذا الدليل: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **ملاحظة** `--al` تعني أن `git` ستعرف أيضا إذا كنت قد حذفت الملفات (بشكل افتراضي، فإنها ستعرف فقط الملفات الجديدة / المعدلة). تذكر أيضا (من الفصل 3) أن `.` تعني الدليل الحالي. + +قبل رفع جميع الملفات دعنا نرى ماذا سترفع `git` ( جميع الملفات التي ترفعها `git` يجب ان تضهر باللون الأخضر): + +{% filename %}command-line{% endfilename %} + + $ git status + + +نحن تقريبا هناك، الآن حان الوقت لنقول لها ان تحفض هذه التغييرات في تاريخها. سنعطيه "رسالة التزام" حيث نصف ما قمنا بتغييره. يمكنك كتابة ما تريد في هذه الحالة ، لكن من الأفضل ان تكتب شيء يدل على ما قمت بفعله حتى تتذكر في المستقبل. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "Changed the HTML for the site." + + +> **ملاحظة** تأكد من استخدام علامات الاقتباس المزدوجة حول رسالة الالتزام. + +عندما نقوم بذالك نرفع او ندفع بتعديلاتنا إلى GitHub: + +{% filename %}command-line{% endfilename %} + + $ git push + + +### اسحب التعليمات الجديدة إلى PythonAnywhere، وأعد تحميل تطبيق الويب + +* افتح [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) واذهب الى **Bash console** او افتح واحدة جديدة وشغل هذا الأمر: + +{% filename %}command-line{% endfilename %} + + $ cd ~/my-first-blog + $ git pull + [...] + + +وشاهد تعليماتك البرمجية يتم تحميلها ،اذا اردت ان ترى ان كانت قد وصلت ، يمكنك الإنتقال الى **Files tab** ورؤية تعليماتك في PythonAnywhere. + +* وأخيرا، انتقل إلى علامة التبويب [Web tab](https://www.pythonanywhere.com/web_app_setup/) واضغط على **Reload**. + +يجب أن يكون التحديث مباشر! امضي قدما وحدث موقع الويب الخاص بك في المتصفح. يجب أن تكون التغييرات مرئية. :) \ No newline at end of file diff --git a/ar/install_git.md b/ar/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/ar/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/ar/installation/README.md b/ar/installation/README.md new file mode 100644 index 00000000000..c32e07b34b5 --- /dev/null +++ b/ar/installation/README.md @@ -0,0 +1,58 @@ +# إذا كنت تستخدم البرنامج التعليمي في المنزل + +إذا كنت تستخدم البرنامج التعليمي في المنزل وليس في أحد [أحداث "جانغو للفتيات"](https://djangogirls.org/events/)، يمكنك تخطي هذا الفصل الآن والانتقال مباشرة إلى الفصل ["كيف يعمل الإنترنت" ](../how_the_internet_works/README.md). + +وهذا يرجع إلى أننا نغطي هذه الأشياء في البرنامج التعليمي كله على أي حال، وهذه مجرد صفحة إضافية تقوم بجمع كافة إرشادات التثبيت في مكان واحد. يشمل حدث دجانغو للفتيات امسية للتثبيت بحيث نقوم بتثبيت كل شيء، حتى لا نعاني اثناء حلقات العمل، هذا سيكون مفيدا بالنسبة لنا. + +إذا وجدت أنها مفيدة، يمكنك المتابعة من خلال هذا الفصل أيضا. ولكن إذا كنت تريد البدء في تعلم الأشياء قبل تثبيت مجموعة من الأشياء على جهاز الكمبيوتر الخاص بك، انتقل من هذا الفصل وسوف نشرح جزء التثبيت لكم في وقت لاحق. + +حظا سعيدا! + +# التثبيت + +في حلقة العمل سوف نبني مدونة، هناك عدد قليل من مهام الإعداد في البرنامج التعليمي الذي سيكون جيدا للعمل سلفا حتى أن كنت على استعداد لبدء التكويد في ذاك اليوم. + + {% include "/chromebook_setup/instructions.md" %} + + + +# تثبيت بايثون + +{% include "/python_installation/instructions.md" %} + +# قم بإعداد بيئة افتراضية وتثبيت جانغو + +{% include "/django_installation/instructions.md" %} + +# ركب محرر اكواد + +{% include "/chromebook_setup/instructions.md" %} + +# تثبيت Git + +{% include "/django_installation/git.md" %} + +# إنشاء حساب Github + +زر [GitHub.com](https://www.github.com) وسجل حساب مستخدم جديد، مجاناً. + +# قم بإنشاء حساب بايثون في كل مكان + +{% include "/django_installation/pythonanywhere.md" %} + +# ابدأ بالقراءة + +تهانينا، انت جاهز الأن وعلى استعداد للإنطلاق! إذا كان لا يزال لديك بعض الوقت قبل انعقاد حلقة العمل، سيكون من المفيد بدء قراءة عدد قليل من فصول البداية: + +* [كيف تعمل الإنترنت](../how_the_internet_works/README.md) + +* [مقدمة لسطر الأوامر](../intro_to_command_line/README.md) + +* [مقدمة إلى بايثون](../python_introduction/README.md) + +* [ما هو جانغو؟](../django/README.md) + +# استمتع بالحلقة! + +عند البدء في حلقة العمل، عليك أن تكون قادر على الذهاب مباشرة إلى [أول مشروع جانغو!](../django_start_project/README.md) لأنك غطيت كل الموارد في الفصول السابقة. \ No newline at end of file diff --git a/ar/instructions.md b/ar/instructions.md new file mode 100644 index 00000000000..be0a284adad --- /dev/null +++ b/ar/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +Creating a `virtualenv` on both Linux and OS X is as simple as running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/ar/intro_to_command_line/README.md b/ar/intro_to_command_line/README.md new file mode 100644 index 00000000000..8bff2ce6a68 --- /dev/null +++ b/ar/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# مقدمة لواجهة سطر الأوامر + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [Your new friend: Command Line](https://www.youtube.com/watch?v=jvZLWhkzX-8). + +أنه مثير، أليس كذلك؟! عليك كتابة السطر الأول الخاص بك من التعليمات البرمجية في بضع دقائق فقط! :) + +**دعونا نقدم لكم صديقكم الأول: سطر الأوامر!** + +الخطوات التالية سوف تظهر لك كيفية استخدام النافدة السوداء التي يستخدمها جميع الهكر. قد تبدو مخيفه قليلاً في البداية ولكن حقاً أنها مجرد موجه تنتظر الأوامر منك. + +> **ملاحظة** يرجى ملاحظة أن طوال هذا الكتاب يمكننا استخدام عبارات 'الدليل' و 'مجلد' بالتبادل ولكنها واحدة ونفس الشيء. + +## ما هو سطر الأوامر؟ + +النافذة، والتي عادة ما تسمى **سطر الأوامر** أو **واجهة سطر الأوامر**، هو تطبيق يستند إلى النص للعرض، والمناولة، ومعالجة الملفات الموجودة على جهاز الكمبيوتر الخاص بك. أنه يشبه إلى حد كبير ويندوز إكسبلورر أو الباحث في Mac، ولكن دون واجهة رسومية. أسماء أخرى لسطر الأوامر هي: *cmd*, *CLI*, *prompt*, *console* أو *terminal*. + +## إفتح واجهة سطر الأوامر + +لبدء بعض التجارب نحن بحاجة إلى فتح واجهة سطر الأوامر لدينا أولاً. + + + +إذهب الى نافدة البداية ← نضام وندوز ← موجه الأوامر. + +> على الإصدارات القديمة من ويندوز، ابحث في قائمة ابدأ > كافة البرامج > ملحقات > موجه الأوامر. + + + + + +انتقل إلى التطبيقات → الأدوات المساعدة → تيرمينال. + + + + + +أنها على الأرجح تحت تطبيقات ← اكسسوارات ← تيرمينال، ولكن قد تعتمد على النظام الخاص بك. إذا لم يكن هناك، فقط بحث في جوجل + + + +## موجه + +يجب أن تشاهد الآن نافذة بيضاء أو سوداء تنتظر الأوامر الخاصه بك. + + + +إذا كنت على ماك أو لينكس، ربما تشاهد `` $، تماما مثل هذا: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +في Windows، انها علامة `>`، مثل هذا: + +{% filename %}command-line{% endfilename %} + + > + + + + +سيتم إرفاق كل أمر قبل هذه الإشارة ومسافة واحدة، ولكن ليس عليك كتابته. سيقوم جهاز الكمبيوتر بالقيام بذلك نيابة عنك. :) + +> مجرد ملاحظة صغيرة: في الحالة الخاصة بك قد يكون هناك شيء من هذا القبيل `C:\Users\ola >` أو `Olas-MacBook-Air:~ ola$` قبل التوقيع الفوري، وهذا موافق 100 ٪. + +يطلق على الجزء`$` أو `>` أو *موجه سطر الأوامر*، أو *موجه* كإسم قصير. فإنه يطالبك بإدخال شيء هناك. + +في البرنامج التعليمي، عندما نريد منك أن تكتب أمر ما ، سوف نشمل `$` أو `>`، وأحيانا أكثر إلى اليسار. يمكنك تجاهل الجزء الأيسر وما عليك سوى كتابة الأمر الذي يبدأ بعد الموجه. + +## الأمر الأول الخاص بك (ياي!) + +لنبدأ بكتابة هذا الأمر: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +ثم اضغط على `enter`. هذه هي النتيجة لدينا: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +كما ترون، الكمبيوتر قد طبع اسم المستخدم الخاص بك. أنيق، هاه؟ :) + +> حاول كتابة كل أمر؛ لا نسخ ولصق. عليك أن تتذكر هذه الطريقة أكثر! + +## الأساسيات + +كل نظام تشغيل يحتوي على مجموعة مختلفة قليلاً من أوامر سطر الأوامر، لذا تأكد من اتباع التعليمات لنظام التشغيل الخاص بك. دعونا نحاول هذا،هيا بنا؟ + +### الدليل الحالي + +سيكون من الجميل أن نعرف أين نحن الآن، اليس كذالك؟ لنرى. اكتب هذا الأمر وإضغط `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> ملاحظة: 'pwd' تعني 'دليل عمل الطباعة'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> ملاحظة: 'cd' تعني 'تغيير الدليل'. تماما مثل pwd مع powershell يمكنك استخدامه في لينكس أو نظام التشغيل Mac OS X. + + + +ربما سترى شيئا مشابها على الجهاز الخاص بك. عندما تقوم بفتح سطر الأوامر تبدأ عادة في الدليل الرئيسي للمستخدم الخاص بك. + +* * * + +### قائمة الملفات والدلائل + +اذا ماذا فيها ؟ سيكون من الرائع معرفة ذالك ، دعونا نرى: + + + +{% 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 + ... + + +> ملاحظة: في powershell يمكنك أيضا استخدام 'ls' مثل لينكس، ونظام التشغيل Mac OS X. + +* * * + +### تغيير الدليل الحالي + +الآن، دعنا نذهب إلى دليل سطح المكتب: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +تحقق إذا كان تم تغييره حقا: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +ها هي ذا! + +> نصيحة المحترفين: إذا كتبت <`cd D`، ثم ضغطت في `tab` على لوحة المفاتيح، فسيملأ سطر الأوامر تلقائيا بقية الاسم حتى تتمكن من التنقل بشكل أسرع. إذا كان هناك أكثر من مجلد واحد بدءاً من"D"، اضغط مفتاح `tab` مرتين للحصول على قائمة الخيارات. + +* * * + +### إنشاء دليل + +ماذا عن إنشاء دليل للتدرب على سطح المكتب؟ يمكنك القيام بذلك بهذه الطريقة: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% filename %}command-line{% endfilename %} + + > mkdir practice + + + + +سيؤدي هذا الأمر الصغير إلى إنشاء مجلد باسم `practice` على سطح المكتب. يمكنك التحقق إذا كان هناك من خلال النظر في سطح المكتب الخاص بك أو بواسطة تشغيل أمر `dir` أو `ls`! جربها. :) + +> نصيحة للمحترفين: إذا كنت لا تريد كتابة الأوامر نفسها مرارا وتكرارا، فجرب الضغط على `up arrow` و `down arrow` على لوحة المفاتيح للتنقل عبر الأوامر المستخدمة مؤخرا. + +* * * + +### تمارين! + +تحدي صغيرة بالنسبة لك: في الدليل الذي تم إنشاؤه حديثا `practice` ، قم بإنشاء دليل يسمى `test`(استخدم الأمرين `cd` و `mkdir`.) + +#### الحل: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +مبروك + +* * * + +### التنظيف + +لا نريد أن تترك فوضى، لذلك دعونا نزيل كل ما قمنا به حتى هذه النقطة. + +أولاً، نحن بحاجة للعودة إلى سطح المكتب: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% filename %}command-line{% endfilename %} + + > cd .. + + + + +باستخدام `.` مع الأمر `cd` سيتم تغيير الدليل الحالي الخاص بك إلى الدليل الأصل (أي، الدليل الذي يحتوي على الدليل الحالي الخاص بك). + +تحقق أين أنت: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +حان الوقت الآن لحذف دليل `practice`: + +> **انتباه**: حذف الملفات باستخدام `del`, `rmdir` أو `rm` غير قابلة للاسترداد، مما يعني * الملفات ستزول إلى الأبد*! لذا كن حدرا جدا مع هذه الأوامر. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +تم! للتأكد دعونا نتحقق من انك حدفته فعليا: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### خروج + +هذا كل شيء الأن! يمكنك إغلاق سطر الأوامر الآن بأمان. دعونا نفعل ذلكبطريقة الهكر، حسنا؟ :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +جيد ، هاه + +## الملخص + +هنا ملخص لبعض الأوامر المفيدة: + +| الأوامر (في Windows) | الأوامر في (ماك/لينكس) | الوصف | أمثلة | +| -------------------- | ---------------------- | ------------------- | ------------------------------------------------- | +| exit | exit | أغلق النافذة | **exit** | +| cd | cd | تغيير الدليل | **cd test** | +| cd | pwd | إظهار الدليل الحالي | **cd** (Windows) o **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (or del) | rm | حذف الملف | **del c:\test\test.txt** | +| rmdir /S | rm -r | حذف الدليل | **rm -r testdirectory** | + +هذه فقط عدد قليل جداً من الأوامر يمكنك تشغيلها في سطر الأوامر الخاصة بك، ولكن انت لن تستخدم اي شيء اكثر من ذالك هذا اليوم. + +إذا كنت فضولي، [ss64.com](http://ss64.com) يحتوي على مرجع كامل لأوامر لكافة أنظمة التشغيل. + +## مستعد ؟ + +دعونا نغوص في بايثون! \ No newline at end of file diff --git a/ar/python_installation/README.md b/ar/python_installation/README.md new file mode 100644 index 00000000000..2f9998046a7 --- /dev/null +++ b/ar/python_installation/README.md @@ -0,0 +1,15 @@ +# لنبدأ مع بايثون + +وأخيراً نحن هنا! + +ولكن أولاً، دعونا نقول لكم ما هي بايثون. بايثون هي لغة برمجة شعبية جداً والتي يمكن استخدامها لإنشاء المواقع والألعاب والبرامج العلمية، والرسومات والكثير، أكثر بكثير. + +بايثون نشأت في أواخر الثمانينات، وهدفها الرئيسي أن يتمكن البشر من قراءتها (ليس فقط آلألات!). هذا هو السبب في أنها تبدو أبسط من لغات البرمجة الأخرى، ولكن لا تقلق - بايثون قوية ايضا! + +# تركيب بايثون + +> **ملاحضة**إذا كنت تستخدم كروم بوك تخطى هذا القسم وتابع الإرشادات الموجودة في [التركيب على كروم بوك](../chromebook_setup/README.md). +> +> **ملاحضة** اذا كنت قد عملت على تعليمات التركيب من قبل ، يمكنك الإنتقال الى المستوى الأخر! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/ar/python_installation/instructions.md b/ar/python_installation/instructions.md new file mode 100644 index 00000000000..35e7cfa4a6a --- /dev/null +++ b/ar/python_installation/instructions.md @@ -0,0 +1,106 @@ +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [تثبيت بايثون محرر التعليمات البرمجية](https://www.youtube.com/watch?v=pVTaqzKZCdA). +> +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots) + +دجانغو مكتوبة ببايثون.. نحن بحاجة إلى بايثون للقيام بأي شيء في جانغو. دعونا نبدأ بتثبيته! نحن نريد منك تثبيت "بايثون 3،6"، حتى إذا كان لديك أي إصدار سابق، سوف تحتاج إلى ترقية. + + + +أولا تحقق ان كان حاسوبك يستخدم نسخة 32 بت او 64 بت من وندوز, ، عن طريق الضغط على مفتاح ويندوز + مفتاح Pause/Break الذي سيقوم بفتح معلومات النظام الخاص بك، وإلقاء نظرة على السطر "نوع النظام". يمكنك تحميل بايثون ل Windows من https://www.python.org/downloads/windows/. انقر فوق "Latest Python 3 Release - Python x.x.x". إذا كان جهاز الكمبيوتر الخاص بك يقوم بتشغيل إصدار **64 بت** من Windows، حمل **Windows x86-64 executable installer**. وبخلاف ذلك، حمل **Windows x86 executable installer**. بعد تحميل المثبت، ينبغي تشغيله (انقر نقراً مزدوجاً على الملف) واتبع الإرشادات الموجودة هناك. + +شيء واحد يجب عليك الإنتباه له أثناء التثبيت ستلاحظ علامة نافذة "إعداد". تأكد من وضع علامة في خانة الاختيار "Add Python 3.6 to PATH" وانقر فوق "التثبيت الآن"، كما هو موضح هنا: + +![لا تنس إضافة بيثون إلى المسار](../python_installation/images/python-installation-options.png) + +في الخطوات المقبلة، عليك استخدام سطر أوامر Windows (والذي سنتكلم عنه ايضا). الآن، إذا كنت بحاجة لكتابة بعض الأوامر، انتقل إلى قائمة ابدأ ← نظام Windows ← موجه الأوامر. يمكنك أيضا الضغط على مفتاح Windows واضغط مفتاح "R"- حتى تضهر نافدة "Run". لفتح سطر الأوامر، اكتب "cmd" وإضغط على أدخل في "Run". (في الإصدارات الأحدث من Windows، قد تحتاج إلى البحث عن "موجه الأوامر"، نظراً لأنه في بعض الأحيان مخفي.) + +![أكتب "cmd" في نافدة "Run"](../python_installation/images/windows-plus-r.png) + +ملاحضة: اذا كنت تستخدم نسخة قديمة من وندوز ( 7، فيستا، او اي نسخة قديمة) وبايثون 3.6 فشلت في التنصيب يكنك تجريب هذا: + +1. تثبيت كافة تحديثات Windows ومحاولة تثبيت بايثون 3.6 مرة أخرى؛ أو +2. تثبيت [نسخة اقدم من بايثون](https://www.python.org/downloads/windows/) مثال [3.4.6](https://www.python.org/downloads/release/python-346/). + +إذا قمت بتثبيت إصدار قديم من بايثون، شاشة التثبيت قد تبدو مختلفة بعض الشيء مما هو مبين أعلاه. تأكد من أنك قمت بالتمرير لأسفل لرؤية "Add python.exe to Path"، ثم انقر فوق الزر الموجود على الجانب الأيسر واختر "Will be installed on local hard drive": + +![إضافة بايثون إلى المسار، الإصدارات القديمة](../python_installation/images/add_python_to_windows_path.png) + + + + + +> **ملاحظة** قبل أن تقوم بتثبيت بايثون على نظام التشغيل OS X، عليك التأكد من إعدادات ماك إذا كانت تسمح بتثبيت الحزم التي ليست من المتجر. إذهب إلى "تفضيلات النظام" (في مجلد التطبيقات)، انقر فوق "الأمان الخصوصية"، ثم علامة التبويب "عام". إذا كانت " السمحاح بالتطبيقات للتحميل من " موضوعة على تطبيقات أبستور فقط غيرها إلى " تطبيقات أبستور و المطورين الغير المعرفين " + +يجب عليك زيارة هذا الموقع وتحميل مثبت بايثون https://www.python.org/downloads/release/python-361/: + +* تحميل ملف *مثبت Ma c OS X 64-بت/32-بت * ، +* انقر نقراً مزدوجاً فوق *python-3.6.1-macosx10.6.pkg* لتشغيل المثبت. + + + + + +من المحتمل جدا ان لديك نسخة بايثون مثبتة بالفعل ، للتحقق ادخل الأوامر التالية في وحدة التحكم: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +إذا كان لديك 'نسخة مايكرو' مختلفة من بايثون منصبة، مثل 3.6.0، إذا ليس عليك الترقية. إذا لم تنصب بايثون ، أي انك تريد نسخة مغايرة ، يمكنك تثبيته على النحو التالي: + + + + + +استخدم هذا الأمر في وحدة التحكم الخاصة بك: + +{% filename %} baris perintah {% endfilename %} + + $ sudo apt-get install python3.6 + + + + + + +استخدم هذا الأمر في وحدة التحكم الخاصة بك: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +إذا كنت تستخدم إصدار فيدورا قديم قد تحصل على خطأ لم يتم العثور على الأمر dnf. في هذه الحالة تحتاج إلى استخدام yum بدلاً من ذلك. + + + + + +استخدم هذا الأمر في وحدة التحكم الخاصة بك: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +تحقق من أن عملية التثبيت كانت ناجحة بفتح موجه الأوامر ثم تشغيل الأمر `python3`: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**ملاحظة:** إذا كنت على ويندوز، و حصلت على رسالة خطأ أنه لم يتم العثور على `python3`، حاول استخدام `python` (دون `3`) وتجربة اذا كان لا يزال هنا نسخة من 3.6 بيثون. + +* * * + +إذا كان لديك اي سؤال ، او حصل شي ما وليس لديه اي فكرة عن ما حصل ، رجاء إستشر مدربك! أحيانا لا تسير الأمور بسلاسة، لذا من الأفضل أن تطلب المساعدة من شخص لديه خبرة أكبر. \ No newline at end of file diff --git a/ar/python_introduction/README.md b/ar/python_introduction/README.md new file mode 100644 index 00000000000..f22d975b62e --- /dev/null +++ b/ar/python_introduction/README.md @@ -0,0 +1,1063 @@ +# مقدمة إلى بايثون + +> هذا القسم يستند على دورة تعليمية من فتيات الجزر المهووسات (https://github.com/ggcarrots/django-carrots). + +دعنا نكتب بعض التعليمات البرمجية! + +## موجه بايثون + +> للقراء في المنزل: تم تغطية هذا الجزء في فيديو [ أساسيات بايثون: عدد صحيح، سلاسل، قوائم، متغيرات وأخطاء ](https://www.youtube.com/watch?v=MO63L4s-20U). + +لبدء العمل ببايثون، نحتاج إلى فتح *سطر الأوامر* على جهاز الكمبيوتر. يجب عليك ان تعرف كيف تفعل ذالك - لقد تعلمته في [مقدمة لسطر الأوامر](../intro_to_command_line/README.md). + +عندما تكون مستعدا، اتبع الإرشادات أدناه. + +نريد فتح وحدة تحكم بيثون، لذلك اكتب في `python` على ويندوز أو `python3` على نظام التشغيل ماك / لينوكس واضغط على `enter`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.1 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## أمر بايثون الأول الخاص بك! + +بعد تشغيل الطلب في بايثون ، تغير الطلب إلى `>>>`. وهذا يعني بالنسبة لنا الآن انه يمكننا استخدام الأوامر في لغة بايثون فقط. ليس عليك الكتابة في `>>>` بايثون سيقوم بذالك. + +إذا كنت ترغب في إنهاء وحدة تحكم بايثون ، فقط اكتب `exit()` أو استخدام الاختصار `Ctrl + Z` ل Windows و `Ctrl + D` ماك/لينكس. فإنك لن ترى `>>>`أبدا. + +في الوقت الحالي، نحن لا نريد الخروج من وحدة تحكم بايثون. نريد أن نتعلم المزيد. دعونا نبدأ بكتابة بعض الرياضيات، مثل `2 + 3` و `enter`. + +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +لطيف! انظر كيف برز الجواب؟ بيثون يعرف الرياضيات! يمكنك محاولة الأوامر الأخرى مثل: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +لإجراء حساب ، قل 2 إلى القوة 3، نكتب: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +استمتع لبعض الوقت مع هذا ، وعد إلى هنا + +كما ترون، بايثون هي الة حاسبة عضيمة. إذا كنت تتساءل ماذا يمكنك أن تفعل… + +## سلسلة + +ماذا عن اسمك؟ اكتب الاسم الأول في علامات اقتباس مثل هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" +'Ola' +``` + +لقد أنشأت الآن السلسلة الأولى! هو تسلسل أحرف يمكن معالجتها بواسطة جهاز الكمبيوتر. يجب ان تبدأ السلسلة وتنتهي بنفس الحرف. قد يكون هذا واحد(`'`)) أو الضعف (`"`)) اقتباس (لا فرق!) الإقتباس يقول لبايثون انه هناك سلسلة. + +السلاسل يمكن أن تكون مربوطة معا. جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +يمكنك أيضا ضرب السلاسل مع عدد: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +إذا كنت بحاجة إلى وضع علامة اقتباس أحادية داخل السلسلة الخاصة بك, لديك طريقتين للقيام بذلك. + +استخدام علامات الاقتباس المزدوجة: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +أو الهروب من الفاصلة بخط مائل (`` \): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +لطيف، هاه؟ لرؤية اسمك بالأحرف الكبيرة، اكتب: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +لقد استخدمت `upper` **method** للتو في السلسلة الخاصة بك! وهناك طريقة (مثل `upper()`) عبارة عن سلسلة من التعليمات التي يجب على بايثون تنفيذها على كائن معين (`"Ola"`) بمجرد استدعائه. + +إذا كنت تريد أن تعرف عدد الحروف الواردة في اسمك، هناك **function** لذلك أيضا! + +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +أتساءل لماذا في بعض الأحيان أستدعي الدالات بواسطة `.` في نهاية سلسلة (مثل `"Ola".upper()`)، وفي بعض الأحيان يمكنك استدعاء دالة أولاً ووضع السلسلة في الأقواس؟ حسنا، في بعض الحالات، تنتمي المهام إلى أشياء، مثل `upper()`, ، والتي لا يمكن تنفيذها إلا على السلاسل. في هذه الحالة نسمي المهام ب **method**. مرات اخرى، المهام لا تنتمي إلى أي شيء محدد، ويمكن استخدامها على أنواع مختلفة من الكائنات، مثل `len()`. لهذا نحن نعطي `"Ola"` اعدادات الى المهمة `len`. + +### مُلخّص + +طيب، يكفينا سلآسل ، حتى الأن لقد تعلمت: + +- **the prompt** كتابة الأوامر (كودات) في موجه اوامر بايثون يعطينا اجابات في بايثون +- **numbers and strings** - في بايثون تستخدم الأرقام للرياضيات والسلاسل للكائنات النصية +- **operators** مثل `+` و `*`, تجمع بين القيم لتنتج واحدة جديدة +- **functions** مثل `upper()` و `len()` تنفذ إجراأت على الكائنات. + +هذه هي الأساسيات لكل لغة برمجة تتعلمها. أنت مستعد لشيء أكثر صعوبة؟ ونحن نراهن على ذالك! + +## أخطاء + +دعنا نجرب شيئا جديداً. يمكن أن نحصل على طول عدد بنفس الطريقة التي يمكن أن نجد بها طول اسمنا؟ اكتب في `len(304023)` واضغط `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> 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(str(304023)) +6 +``` + +لقد كان مجديًا! قمنا باستخدام الدالة `str` داخل الدالة `len`. `str ()` تحويل كل شيء إلى سلاسل. + +- الدالة `str` تحول الأشياء إلى **strings + + - الدالة `int` تحول الأشياء إلى **integers** + + > هام: علينا تحويل الأرقام إلى نص، ولكن لا يمكن بالضرورة تحويل النص إلى أرقام – ماذا ستكون `int('hello')` على أي حال؟ + + ## المتغيرات + + مفهوم هام في البرمجة وهو المتغيرات. المتغير ليس أكثر من اسم لشيء يمكن استخدامه في وقت لاحق. يستخدم المبرمجون هذه المتغيرات لتخزين البيانات، وجعل التعليمات البرمجية الخاصة بهم أكثر قابلية للقراءة، لذالك هم ليسو بحاجة لتدكر كل شيء. + + لنفرض أننا نريد إنشاء متغير جديد يسمى `name`: + + {% filename %}command-line{% endfilename %} + + ```python +>>> name = "Ola" +``` + +اكتب اسم يساوي Ola. + +كما لاحظت، فإن البرنامج لم يعد أي شيء كما فعل من قبل. فكيف نعرف أن المتغير موجود بالفعل؟ ما عليك سوى إدخال `name` واضغط على `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +يآآاي! المتغير الأول الخاص بك! :) يمكنك دائماً تغيير ما يشير إليه: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +يمكنك استخدامه في وظائف ايضا: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +رائع، أليس كذلك؟ بالطبع، المتغيرات يمكن أن تكون أي شيء أرقام أيضا! جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +ولكن ماذا لو استخدمنا اسم خاطئ؟ هل يمكنك تخمين ما يمكن أن يحدث؟ دعونا نحاول! + +{% filename %}command-line{% endfilename %} + +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +خطأ! كما ترون، بيثون لديه أنواع مختلفة من الأخطاء ويسمى هذا **NameError**. سيعطيك بايثون هذا الخطأ إذا حاولت استخدام متغير لم يتم تعريفه حتى الآن. إذا واجهت هذا الخطأ في وقت لاحق، تحقق من التعليمات البرمجية الخاصة بك لمعرفة إذا كنت أخطأت في أي أسماء. + +العب بهذه التعليمات لبعض الوقت، وانضر ما يمكن ان تفعله! + +## وظيفة الطباعة + +جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` + +عندما تكتب `name`, فقط، يستجيب مترجم بايثون مع*representation* المتغير 'نيم'، وهو الحرف M-a-r-i-a، المحاط بعلامات اقتباس مفردة، ''. عندما تقول `print(name)`, بايثون ستقوم ب "طباعة" محتويات المتغير إلى الشاشة، دون علامات الاقتباس، وهو أكثرإتقانا. + +وكما سنرى لاحقاً، `print()` مفيد أيضا عندما نريد طباعة الأشياء من داخل المهام، أو عندما نريد طباعة الأشياء في أسطر متعددة. + +## القوائم + +بجانب السلاسل والأعداد الصحيحة، بايثون لديه كل الأنواع المختلفة من الكائنات. الآن نحن بصدد إدخال واحد يسمى **list**. القوائم هي بالضبط ما تعتقد: الكائنات التي هي قوائم لكائنات الأخرى. :) + +امضي قدما وأنشئ قائمة: + +{% filename %}command-line{% endfilename %} + +```python +>>> [] +[] +``` + +نعم، هذه القائمة فارغة. ليست مفيدة جدا، أليس كذلك؟ دعونا ننشئ قائمة من أرقام اليانصيب. نحن لا نريد أن نكرر ذالك طوال الوقت، لذلك سنضعها في متغير أيضا: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +حسنا، لدينا قائمة! ماذا يمكننا أن نفعل حيال ذلك؟ دعونا نرى كم عدد اليانصيب هناك في القائمة. هل لديك أي فكرة عن أي وظيفة يجب عليك استخدامها لذلك؟ أنت تعرف هذا بالفعل! + +{% filename %}command-line{% endfilename %} + +```python +>>> len(lottery) +6 +``` + +نعم! `len()` يمكن أن تعطيك عددا من الكائنات في قائمة. مفيد، أليس كذلك؟ ربما سنقوم بترتيبها الآن: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.sort() +``` + +هذا لا يعيد أي شيء، انها مجرد تغييرات للترتيب الذي يظهر الأرقام في القائمة. دعونا نطبعه مرة أخرى ونرى ما يحدث: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +كما ترون، يتم فرز الأرقام في القائمة الخاصة بك الآن من أدنى إلى أعلى القيمة. مبروك! + +ربما نريد عكس هذا الترتيب؟ دعونا نفعل ذلك! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +إذا كنت ترغب في إضافة أي شيء إلى القائمة الخاصة بك، يمكنك القيام بذلك عن طريق كتابة هذا الأمر: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +إذا كنت ترغب في إظهار الرقم الأول فقط، يمكنك القيام بذلك باستخدام **indexes**. الفهرس هو العدد الذي يقول أين يحدث عنصر في قائمة. المبرمجين يفضلون بدء العد من 0، وبالتالي فإن الكائن الأول في قائمتك هو في مؤشر 0، والكائن القادم هو في 1، وما إلى ذلك. جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` + +كما ترون، يمكنك الوصول إلى كائنات مختلفة في القائمة الخاصة بك باستخدام الاسم في قائمة الفهرس للكائن داخل أقواس معقوفة. + +لحذف شيء من القائمة الخاصة بك سوف تحتاج إلى استخدام **indexes** كما تعلمنا أعلاه وأسلوب `pop()`. دعونا احد الأمثلة ونعزز ما تعلمناه سابقا. سنقوم بحذف الرقم الأول من قائمتنا. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +انه يعمل كالحصان! + +للمتعة الإضافية، حاول بعض الفهارس الأخرى: 6، 7، 1000،-1 أو-6-1000. انظر إذا كان يمكنك التنبؤ بالنتيجة قبل محاولة الأمر. منطقي؟ + +يمكن أن تجد قائمة بجميع الأساليب القائمة المتوفرة في هذا الفصل من وثائق بايثون: https://docs.python.org/3/tutorial/datastructures.html + +## القواميس + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c). + +القاموس مماثل للقائمة، ولكن يمكنك الوصول إلى القيم عن طريق البحث عن المفتاح بدلا من الفهرس الرقمي. المفتاح يمكن أن يكون أي سلسلة أو رقم. تعريف جملة لبنآء قاموس فارغ: + +{% filename %}command-line{% endfilename %} + +```python +>>> {} +{} +``` + +هذا يدل على أنك قمت بإنشاء قاموس فارغ للتو. يآآاي! + +والآن، حاول كتابة الأمر التالي (محاولة استبدال المعلومات الخاصة بك، ايضا): + +{% filename %}command-line{% endfilename %} + +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` + +مع هذا الأمر، الذي أنشأته للتو متغير يسمى `participant` مع ثثلاثة أزواج القيمة الرئيسية: + +- المفتاح `name` يشير إلى قيمة`'Ola'`(كائن `string`)، +- `country` يشير إلى `'Poland'` (`string` أخرى)، +- ويشير `favorite_numbers` إلى `[7، 42، 92]` (`list` بثلاثة أرقام). + +يمكنك التحقق من محتوى المفاتيح الفردية مع بناء الجملة التالي: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(participant['name']) +Ola +``` + +انظر، انها مماثلة للقائمة. ولكن لا تحتاج إلى تذكر الفهرس - فقط الاسم. + +ماذا يحدث إذا طلبنا من بايثون قيمة مفتاح غير موجود؟ هل يمكنك التخمين؟ دعونا نحاول ونرى! + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` + +انضر، خطأ آخر! هذا **KeyError**. بايثون مفيد ويخبرك بأن مفتاح `'age'` غير موجود في هذا القاموس. + +متى يجب استخدام قاموس أو قائمة؟ حسنا، هذه نقطة جيدة للتفكير. فقط فكر في حل قبل النظر في الجواب في السطر التالي. + +- هل تحتاج فقط إلى تسلسل أمر من العناصر؟ انتقل إلى القائمة. +- هل تحتاج إلى ربط القيم مع مفاتيح، حتى تتمكن من البحث عنها بكفاءة (عن طريق مفتاح) في وقت لاحق؟ إستخدم المعجم. + +القواميس، مثل القوائم، و *mutable*، بمعنى أنه يمكن تغييرها بعد إنشائها. يمكنك إضافة أزواج مفتاح – القيمة الجديدة إلى قاموس بعد إنشائه، هكذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +مثل القوائم، باستخدام طريقة `len()` على القواميس ترجع عدد أزواج القيمة الرئيسية في القاموس. إمضي قدما واكتب هذا الأمر: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +آمل أن يكون هذا منطقيا حتى الآن. :) هل انت على استعداد لمتعة أكثر مع القواميس؟ قراءة لبعض الأشياء المدهشة. + +يمكنك استخدام الأسلوب `pop()` لحدف عنصر من القاموس. لنفترض أنك تريد حذف المدخل المقابل للمفتاح `'favorite_numbers'`, ، اكتب فقط الأمر التالي: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +كما ترون من المخرج، تم حذف زوج مفتاح القيمة المقابلة لمفتاح 'favorite_numbers'. + +فضلا عن ذلك، يمكنك أيضا تغيير قيمة مرتبطة بمفتاح تم إنشاؤه مسبقاً في القاموس. اكتب هذا الأمر: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +كما ترون، تم تغيير قيمة المفتاح `'country'` من `'Poland'` إلى `'Germany'`. :) مثير؟ مرحى! لقد تعلمت للتو شيء آخر مدهش. + +### الملخص + +مدهش! أنت تعرف الكثير عن البرمجة الآن. لقد تعلمت في هذا الجزء الأخير حول: + +- **أخطاء** – يمكنك الآن معرفة كيفية قراءة وفهم الأخطاء التي تظهر إذا كان بايثون لم يفهم امر اعطيته له +- **المتغيرات** –أسماء الكائنات التي تسمح لك بتكويد أكثر سهولة وجعل التعليمات البرمجية الخاصة بك أكثر قابلية للقراءة +- **قوائم** – قوائم الكائنات المخزنة في ترتيب معين +- **قواميس** – الكائنات المخزنة كقيمة مفتاح-أزواج + +متحمس للجزء القادم؟ :) + +## مقارنة الأشياء + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في فيديو [Python Basics: Dictionaries](https://www.youtube.com/watch?v=7bzxqIKYgf4). + +جزء كبير من البرمجة ينطوي على مقارنة الأشياء. ما هو أسهل شيء للمقارنة؟ أرقام، بالطبع. دعونا نرى كيف يعمل: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +``` + +أعطينا بايثون بعض الأرقام للمقارنة. كما ترون،بايثون لا يمكنها مقارنة الأرقام فقط، ولكن يمكنها أيضا مقارنة نتائج الأسلوب. لطيف، هاه؟ + +هل تتساءل لماذا وضعنا اثنين من العلامات المتساوية `==` بجانب بعضها البعض للمقارنة إذا كانت الأرقام متساوية؟ ونحن نستخدم `=` واحد لتعيين القيم للمتغيرات. دائماً، تحتاج **دائماً** إلى وضع اثنين من--= = ``--إذا كنت ترغب في معرفة ما إذا كانت الأمور مساوية لبعضها البعض. يمكننا أن نقول أيضا أن الأمور غير متساوية مع بعضها البعض. لذالك نستخدم هذه الرموز `!=` كما هو مبين في المثال أعلاه. + +أعطي بايثون مهمتان اخرتان: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +لقد شهدنا `>` و `<`، ولكن ما فعله `> =` و `< =` يعني؟ اقرأهم بهذه الطريقة: + +- `x_>` y يعني: x أكبر من y +- `x_<` y يعني: x أقل من y +- x `<=` y يعني: x أقل من أو يساوي y +- x `> =` يعني y: x أكبر من أو يساوي y + +رائع! تريد القيام بذالك مرة اخرى؟ جرب هذا: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 3 > 2 or 2 < 1 +True +``` + +يمكنك أن تعطي بايثون العديد من الأرقام للمقارنة كما تريد، وسوف تعطيك الجواب! ذكية جدا، أليس كذلك؟ + +- **و**-إذا قمت باستخدام عامل التشغيل `and`، كل المقارنات يجب أن تكون صحيحة في النظام لكي يكون الأمر كله صحيح +- **أو** – إذا كنت تستخدم عامل التشغيل `or`، واحد فقط من المقارنات يجب أن يكون صحيحاً في النظام لكي يكون الأمر كله صحيح + +هل سمعت عبارة "مقارنة التفاح بالبرتقال"؟ دعونا نحاول ما يعادل بايثون: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and 'str' +``` + +هنا ترى أنه كما هو الحال في التعبير، بايثون غير قادرة على مقارنة عدد(`int`) وسلسلة (`str`). بدلاً من ذلك، فإنه يظهر **TypeError** ويقول لنا لا يمكن مقارنة هذين النوعين معا. + +## Boolean + +وبالمناسبة، لقد تعلمت للتو نوع جديد من الكائنات في بايثون. تسمى **Boolean**. + +هناك اثنين فقط من كائنات Boolean : + +- صحيح +- خطأ + +لتفهم بايثون ذالك ، تحتاج الى كتابتها دائما ك "صحيح" (الحرف الأول كبير، مع بقية الحروف صغيرة). **true, TRUE,، وtRUE لن تنجح – الوحيدة التي ستنجح هي True.** (نفس الأمر ينطبق على 'False' كذلك، بطبيعة الحال.) + +يمكن أن تكون Booleans متغيرات، أيضا! انظر هنا: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +يمكنك أيضا القيام بذلك بهذه الطريقة: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +تدرب واستمتع مع Booleans قبل محاولة تشغيل الأوامر التالية: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +مبروك! Booleans واحدة من أروع ملامح البرمجة، وانت تعلمت للتو كيفية استخدامها! + +# احفظه! + +> للقراء في المنزل: هذا الفصل تم التكلم عنه في فيديو [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk). + +حتى الآن كنا نكتب كل ما لدينا من تعليمات بايثون في المترجم، مما يحدنا من إدخال سطر واحد من التعليمات البرمجية في وقت واحد. يتم حفظ البرامج العادية في الملفات ويتم تنفيذها من قبل لغتنا البرمجية **interpreter** أو **compiler**. حتى الآن كنا نقوم بتشغيل برامجنا سطر واحد في كل مرة في بايثون **interpreter**. سنحتاج إلى أكثر من سطر واحد من التعليمات البرمجية للمهام القليلة التالية، لذلك سنحتاج بسرعة إلى: + +- قم بإنهاء مترجم بايثون +- فتح محرر التعليمات البرمجية لدينا الاختيار +- حفظ بعض التعليمات البرمجية في ملف بايثون جديد +- تشغيله! + +للخروج من مترجم بايثون كنا نستعمل، ببساطة اكتب دالة `exit()` + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` + +سيؤدي ذلك إلى إعادة توجيهك إلى موجه الأوامر. + +في وقت سابق، اخترنا محرر رموز من قسم [code editor](../code_editor/README.md). سنحتاج إلى فتح المحرر الآن وكتابة بعض الأكواد في ملف جديد: + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +ومن الواضح أنك مطور بايثون محنك جداً الآن، لذا لا تتردد في كتابة بعض التعليمات البرمجية التي تعلمتها اليوم. + +الآن نحن بحاجة إلى حفظ الملف وإعطائه اسماً وصفياً. دعونا نسمي الملف **python_intro.py** وحفظه إلى سطح المكتب الخاص بك. يمكننا تسمية الملف أي شيء نريده، ولكن الجزء المهم هنا هو التأكد من انتهاء الملف ب **.py**. ويقول امتداد **.py** لنظام التشغيل أن هذا **Python executable file + +> يجب أن تلاحظ واحدة من أروع شيء عن المحررين الأكواد: الألوان! في وحدة تحكم بايثون، كان كل شيء بنفس اللون. الآن يجب أن ترى أن الدالة `print` هي لون مختلف عن السلسلة. وهذا ما يسمى "syntax highlighting"، وهي ميزة مفيدة حقاً عند الترميز. سيعطيك لون الأشياء تلميحات مثل السلاسل غير المغلقة أو الأخطاء المطبعية في اسم الكلمة الرئيسية (مثل `def` في إحدى الدالات، والتي سنراها أدناه). وهذا أحد الأسباب التي تجعلنا نستخدم محرر تعليمات برمجية. :) + +مع الملف المحفوظ، حان الوقت لتشغيله! استخدم المهارات التي كنت قد تعلمت في قسم سطر الأوامر، استخدام التيرمينال **change directories** إلى سطح المكتب. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/ar/signup_pythonanywhere.md b/ar/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/ar/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/ar/template_extending/README.md b/ar/template_extending/README.md new file mode 100644 index 00000000000..84d30c776be --- /dev/null +++ b/ar/template_extending/README.md @@ -0,0 +1,147 @@ +# تمديد القالب + +شيء جميل آخر يقدمه جانغو لك هو **تمديد القالب **. ماذا يعني هذا؟ هذا يعني أنه يمكنك استخدام الأجزاء نفسها من HTML لصفحات مختلفة من موقعك على الويب. + +القوالب تساعدك عندما تريد استخدام نفس الشكل او المعلومات اكثر من مرة او في اكثر من مكان. ليس عليك تكرار نفسك في كل ملف. وإذا كنت ترغب في تغيير شيء ما، ليس عليك تغيره في كل قالب, بل ستغيره في قالب واحد! + +## أنشئ القالب الرئيسي + +القالب الرئيسي هو قالب اساسي والذي ستقوم بتمديده اثناء استخدامه في اي صفحة من موقعك. + +لنقم بإنشاء ملف `base.html` في `blog/templates/blog/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +ثم افتحه وانسخ كل شيء من `post_list.html` إلى ملف `base.html`، مثل هذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + +     +        Django Girls blog +         +         +         +         +     +     +         + +        
+            
+                
+                {% for post in posts %} +                    
+                        
+                            {{ post.published_date }} +                        
+                        

{{ post.title }}

+                        

{{ post.text|linebreaksbr }}

+                    
+                {% endfor %} +                
+            
+        
+     + +``` + +ثم في `base.html`، استبدل 1 (كل شيء بين 1 و ``) مع هذا: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}قد تلاحض ان هذا قد غير `{% for post in posts %}` إلى `{% endfor %}` ب: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %}{% endblock %} +``` + +لكن لماذا؟ لقد انشأت `كتلة`! استخدمت علامة القالب `{% block %}` لإنشاء منطقة التي ستضع فيها إتش تي أم ال HTML. ذاك HTML قادم من قالب اخر الذي قام بتمديد هذا القالب (`base.html`). نحن سنريك طريقة فعل ذالك خلال لحضات. + +الآن إحفظ `base.html` وإفتح `blog/templates/blog/post_list.html` مرة أخرى. {% raw %}ستحتاج لحدف كل شي فوق `{% for post in posts %}` وتحت `{% endfor %}`. عند الانتهاء من ذلك، الملف سيبدو هكذا:{% endraw %} + +{% filename %}blog/templates/blog/list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +نريد أن نستخدم هذه كجزء من قالبنا لجميع كتل المحتوى. حان الوقت لإضافة علامات الكتل لهذا الملف! + +{% raw %}You تريد لعلامة كتلتك ان تطابق العلامة في ملف `base.html`. تحتاج أيضا ان تشمل كافة التعليمات البرمجية التي تنتمي إليها في كتل المحتوى الخاص بك. للقيام بذلك، ضع كل شيء بين `{% block content %}` و `{% endblock %}`. مثل هذا: {% endraw %} + +{% filename %}blog/templates/blog/list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +بقي شيء واحد فقط. نحن بحاجة إلى ربط هذين القالبين معا. هذا ما نقصد به توسيع القوالب! سنفعل ذلك عن طريق إضافة علامة تمديد إلى بداية الملف. مثال: + +{% filename %}blog/templates/blog/list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +هذا كل شء! تحقق ان كان موقعك يعمل + +> اذا حصلت على هذا الخطأ `TemplateDoesNotExist`، وهذا يعني انه ليس هناك ملف`blog/base.html` ولديك `runserver` يشتغل في الكونسول. حاول إيقافه (بالضغط على Ctrl+C - مفتاح التحكم و C معا) وإعادة تشغيله من خلال تشغيل أمر python manage.py runserver .

+ \ No newline at end of file diff --git a/ar/whats_next/README.md b/ar/whats_next/README.md new file mode 100644 index 00000000000..1b55afca08e --- /dev/null +++ b/ar/whats_next/README.md @@ -0,0 +1,25 @@ +# ما هي الخطوة التالية؟ + +هنئ نفسك ** أنت رائع تماما ** نحن فخورون بك! <3 + +### ماذا يجب ان تفعل الأن؟ + +خذ قسط من الراحة والاسترخاء. لقد فعلت للتو شيء ضخم حقا. + +بعد ذلك، تأكد من اتباع Django Girls على [ الفيسبوك ](http://facebook.com/djangogirls) أو [ تويتر ](https://twitter.com/djangogirls) للبقاء مطلعا على كل الأحداث. + +### هل يمكنك التوصية بأي موارد إضافية؟ + +نعم! أولا، أمضي قدما وحاول تجربة هذا الكتاب [ Django Girls Tutorial: Extensions ](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). + +لاحقا، يمكنك تجربة الموارد المدرجة أدناه. نحن نوصي بها كلها! + +- [دجانغو البرنامج التعليمي الرسمي](https://docs.djangoproject.com/en/1.11/intro/tutorial01/) +- [دروس المبرمج المبتدئ](http://newcoder.io/tutorials/) +- [كود أكاديمي: دروس بايثون](https://www.codecademy.com/en/tracks/python) +- [كود أكاديمي دروس HTML & CSS](https://www.codecademy.com/tracks/web) +- [دجانغو دروس الجزر](https://github.com/ggcarrots/django-carrots) +- [كتاب تعلم بايثون بالطريقة الصعبة](http://learnpythonthehardway.org/book/) +- [إبدأ مع دجانغو دروس الفيديو](http://www.gettingstartedwithdjango.com/) +- [ملعقتان من جانغو 1.11: أفضل الممارسات لجانغو كتاب إطار الويب](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [ تطبيق مرحبا بالويب: تعلم كيفية بناء تطبيق على شبكة الإنترنت ](https://hellowebapp.com/) - يمكنك أيضا طلب ترخيص الكتاب الإلكتروني مجانا عن طريق الاتصال بتراسي أوسبورن في \ No newline at end of file diff --git a/az-AZ/GLOSSARY.md b/az-AZ/GLOSSARY.md new file mode 100644 index 00000000000..5f7452b317e --- /dev/null +++ b/az-AZ/GLOSSARY.md @@ -0,0 +1,3 @@ +# kod redaktoru + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/az-AZ/README.md b/az-AZ/README.md new file mode 100644 index 00000000000..9878e43a938 --- /dev/null +++ b/az-AZ/README.md @@ -0,0 +1,51 @@ +# Django Girls Dərsliyi + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> Bu iş Creative Commons Attribution-ShareAlike 4.0 Beynəlxalq Lisenziyası altında lisenziyalanmışdır. Bu lisenziyanın bir kopyasına baxmaq üçün, https://creativecommons.org/licenses/by-sa/4.0/ ünvanını ziyarət edin. + +## Xoş Gəldiniz + +Django Girls Dərsliyinizə xoş gəldiniz! Sizi burada görməyə şadıq. :) Bu dərslikdə, sizi veb texnologiyalar başlığı altında bir səyahətə aparacağıq, internetin bildiyimiz kimi işləməsi üçün bir araya gəlməsi lazım olan bütün hissə və parçalara nəzər salacağıq. + +Bütün bilinməyən şeylərdə olduğu kimi, bu da bir macəra dolu səyahət olacaq - ancaq narahat olmayın, çünki cəsarətiniz sayəsində buradasınız və daha da yaxşı olacaqsınız. :) + +## Giriş + +Heç (hələ də) əlaqə qurmadığınız texnologiyanın getdikcə dünya ilə daha çox əlaqəli olduğunu hiss etməmisiniz? Heç bir veb saytın necə hazırlandığı ilə maraqlanıb başlamaq üçün lazım olan motivasiyaya sahib olmamısınız? Proqram təminatı (kod) dünyasının sizin üçün özbaşına bir şeylərə cəhd etmək üçün çox mürəkkəb olduğunu düşünmüsünüz? + +Onda, sizə yaxşı xəbərimiz var! Proqramlaşdırma göründüyü qədər çətin deyil və biz sizə nə qədər əyləncəli ola biləcəyini göstərmək istəyirik. + +Bu dərslik bir sehrlə sizi proqramçıya çevirməyəcək. Əgər bu mövzuda yaxşı olmaq istəyirsinizsə, aylarla, hətta illərlə öyrənməyə və pratika etməyə ehtiyacınız var. Ancaq yenə də sizə göstərmək istəyirik ki, proqramlaşdırma və ya veb sayt yaratmaq göründüyü qədər mürəkkəb deyil. Müxtəlif hissələri bacardığımız qədər izah etməyə çalışacağıq ki, texnologiyadan artıq gözünüz qorxmasın. + +Ümid edirik ki, texnologiyanı sizə bizim qədər sevdirə biləcəyik! + +## Təlim boyunca nələr öyrənəcəksiniz? + +Dərsliyi bitirdikdən sonra kiçik bir işləyən veb tətbiqiniz olacaq: öz bloqunuz. Başqalarının işlərinizi görməsi üçün bloqunuzu necə onlayn edəcəyinizi göstərəcəyik! + +Aşağı yuxarı, belə bir görünüşü olacaq: + +![Şəkil 0.1](images/application.png) + +> Dərsliklə təkbaşına işləyirsinizsə və hər hansı bir problem zamanı sizə kömək edəcək bir məşqçiniz yoxdursa, sizin üçün bir söhbət sistemimiz var: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). Məşqçilərimizdən və daha əvvəl qoşulan şəxslərdən vaxtaşırı orada olmalarını və dərslikdə başqalarına kömək etmələrini xahiş etdik! Orada suallarınızı verməkdən çəkinməyin! + +Yaxşı, [gəlin ən başdan başlayaq...](./how_the_internet_works/README.md) + +## Dərsi evdən izləmək + +Django Girls atelyesində iştirak etmək möhtəşəmdir, ancaq qoşulmağın həmişə mümkün ola bilməyəcəyini də anlayırıq. Buna görə də, bu dərsliyi evdə izləməyini tövsiyə edirik. Evdə oxuyanlar üçün, hazırda dərsliyi təkbaşına izləməyi asanlaşdıracaq videolar hazırlayırıq. Bu hələ də davam edən bir işdir, ancaq daha çoxu tezliklə [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) YouTube kanalında işıqlandırılacaq. + +Artıq əhatə olunmuş hər fəsildə, doğru videoya işarə edən bir bağlantı var. + +## Haqqında və töhfə vermə + +Bu dərs [DjangoGirls](https://djangogirls.org/) tərəfindən aparılır. Əgər səhv tapsanız və ya dərsliyi yeniləmək istəsəniz, zəhmət olmasa [töhfə təlimatlarını izləyin](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## Bu dərsliyi başqa dillərə tərcümə etməyimizə kömək etmək istərdinizmi? + +Hal-hazırda, tərcümələr crowdin.com platformasında saxlanılır: + +https://crowdin.com/project/django-girls-tutorial + +Əgər diliniz [crowdin](https://crowdin.com/)-dəki siyahıda yoxdursa, dili əlavə etməyimiz üçün zəhmət olmasa [yeni bir mövzu aç](https://github.com/DjangoGirls/tutorial/issues/new) vasitəsilə bizi məlumatlandırın. \ No newline at end of file diff --git a/az-AZ/SUMMARY.md b/az-AZ/SUMMARY.md new file mode 100644 index 00000000000..d29ea6916c9 --- /dev/null +++ b/az-AZ/SUMMARY.md @@ -0,0 +1,35 @@ +# İcmal + +* [Giriş](README.md) +* [Quraşdırma](installation/README.md) + * [Əmr Sətri](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Kod Redaktoru](installation/README.md#code-editor) + * [Virtual Mühit](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Quraşdırma (chromebook)](chromebook_setup/README.md) +* [İnternet necə işləyir](how_the_internet_works/README.md) +* [Əmrlər sətrinə giriş](intro_to_command_line/README.md) +* [Python-un quraşdırılması](python_installation/README.md) +* [Kod redaktoru](code_editor/README.md) +* [Python-a giriş](python_introduction/README.md) +* [Django nədir?](django/README.md) +* [Django-nun quraşdırılması](django_installation/README.md) +* [İlk Django layihəniz!](django_start_project/README.md) +* [Django modelləri](django_models/README.md) +* [Django admin](django_admin/README.md) +* [Yerləşdir!](deploy/README.md) +* [Django URL-ləri](django_urls/README.md) +* [Django views – yaratmaq vaxtıdır!](django_views/README.md) +* [HTML-ə giriş](html/README.md) +* [Django ORM (Sorğu setləri)](django_orm/README.md) +* [Şablon içində dinamik verilənlər](dynamic_data_in_templates/README.md) +* [Django şablonları](django_templates/README.md) +* [CSS – gözəlləşdirin](css/README.md) +* [Şablonu genişləndirmə](template_extending/README.md) +* [Tətbiqetmənizi genişləndirin](extend_your_application/README.md) +* [Django Formları](django_forms/README.md) +* [Növbədə nədir?](whats_next/README.md) \ No newline at end of file diff --git a/az-AZ/chromebook_setup/README.md b/az-AZ/chromebook_setup/README.md new file mode 100644 index 00000000000..33cc417f7b5 --- /dev/null +++ b/az-AZ/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook qurulumu + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/az-AZ/chromebook_setup/instructions.md b/az-AZ/chromebook_setup/instructions.md new file mode 100644 index 00000000000..89a515f0dce --- /dev/null +++ b/az-AZ/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Əgər Chromebook istifadə etmirsinizsə, [bu hissəni birbaşa keçə bilərsiniz.](http://tutorial.djangogirls.org/en/installation/#install-python) İstifadə edirsinizsə, qurulum biraz fərqli olacaq. You can ignore the rest of the installation instructions. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Cloud IDE 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 the software. For the duration of the tutorial, cloud IDE 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 IDE sets up for you. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). You can choose one of the cloud IDEs, and follow the instruction of the cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Go to [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Sign up for an account +3. Click *New Server* and choose the Django app +4. Click Terminal button(on the left side of the window) + +Now you should see an interface with a sidebar, buttons at the left. Click "Terminal" button to open terminal window with prompt like this: + +{% filename %}Terminal{% endfilename %} + + $ + + +The terminal on the PaizaCloud Cloud IDE is prepared for your instructions. You can resize or maximize that window to make it a bit bigger. + +#### AWS Cloud9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + yourusername:~/workspace $ + + +This bottom area is your terminal. You can use the terminal to send instructions to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### 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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/az-AZ/code_editor/README.md b/az-AZ/code_editor/README.md new file mode 100644 index 00000000000..84f5f961a3b --- /dev/null +++ b/az-AZ/code_editor/README.md @@ -0,0 +1,11 @@ +# Kod redaktoru + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +Siz kodunuzun birinci sətrini yazmağa balamaq üzrəsiniz, odur ki, kod redaktoru yükləmək vaxtıdır! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. The cloud IDE you chose (PaizaCloud Cloud IDE or AWS Cloud9) includes a code editor, and when you open a file in your IDE from the File menu, you will automatically be using the editor. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/az-AZ/code_editor/instructions.md b/az-AZ/code_editor/instructions.md new file mode 100644 index 00000000000..527c8232a60 --- /dev/null +++ b/az-AZ/code_editor/instructions.md @@ -0,0 +1,37 @@ +Çoxlu müxtəlif editor proqramları (düzənləyici) var və hansını istifadə etmək şəxsi seçimdən asılıdır. Əksər Python proqramçıları qarışıq, amma çox güclü IDE(inteqrallaşdırılmış (birləşdirilmiş) proqramlaşdırma mühiti)-lərdən istifadə edir, məsələn PyCharm kimi. Lakin yeni başlayanlar üçün bu bir qədər az əlverişlidir. Bizim tövsiyə etdiklərimiz isə eyni dərəcədə güclü, amma çox daha sadədır. + +Bizim tövsiyyələrimiz aşağıdakılardır, amma öz müəlliminizdən də soruşa bilərsiniz. + +## Visual Studio Code + +Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + +[Buradan yükləyin](https://code.visualstudio.com/) + +## Gedit + +Gedit is an open-source, free editor, available for all operating systems. + +[Buradan yükləyin](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[Buradan yükləyin](https://www.sublimetext.com/3) + +## Atom + +Atom is another popular editor. It's free, open-source and available for Windows, OS X and Linux. Atom is developed by [GitHub](https://github.com/). + +[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. :) \ No newline at end of file diff --git a/az-AZ/css/README.md b/az-AZ/css/README.md new file mode 100644 index 00000000000..8b2a1665260 --- /dev/null +++ b/az-AZ/css/README.md @@ -0,0 +1,330 @@ +# CSS – make it pretty! + +Bizim blogumuz hələ də son dərəcə eybəcər görünür, hə? Onu gözəlləşdirmək vaxtıdır. Biz bunun üçün CSS istifadə edəcəyik. + +## CSS nədir? + +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? Once more, we'll use something that programmers released on the Internet for free. Reinventing the wheel is no fun, you know. + +## Gəlin Bootstrap istifadə edək! + +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. Now it's developed by volunteers from all over the world! + +## Bootstrapı Quraşdır + +To install Bootstrap, open up your `.html` file in the code editor and add this to the `` section: + +{% 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. So go ahead, open your website and refresh the page. Here it is! + +![Figure 14.1](images/bootstrap1.png) + +Artıq çox gözəl görünür! + +## Django-da statik sənələr + +Nəhayət, biz **static files** adlandırılan sənədlərə daha yaxından baxacağıq. 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. + +### Statik sənədləri (<0>static files) Djangoda hara yerləşdirək + +Django already knows where to find the static files for the built-in "admin" app. Now we 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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +But let's do at least a little. Maybe we could change the color of our headers? 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, h2 a { + color: #C25100; +} + +``` + +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element; the `h2 a` selector does the same thing for `h2` elements. 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 `#C25100`, which is a dark orange. Or you can put your own color here, but make sure it has good contrast against a white background! + +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 element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file in the code editor and add this line at the very beginning of it: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +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 be overriden by 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 static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/az-AZ/deploy/README.md b/az-AZ/deploy/README.md new file mode 100644 index 00000000000..cc2d165200c --- /dev/null +++ b/az-AZ/deploy/README.md @@ -0,0 +1,246 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/az-AZ/deploy/install_git.md b/az-AZ/deploy/install_git.md new file mode 100644 index 00000000000..53fbe28d617 --- /dev/null +++ b/az-AZ/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in word processor programs (e.g., Microsoft Word or LibreOffice Writer), but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for two: in the step where it asks to choose your editor, you should pick Nano, and in the step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/az-AZ/deploy/signup_pythonanywhere.md b/az-AZ/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..555e36731dd --- /dev/null +++ b/az-AZ/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use it for hosting our site, live and on the Internet. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/az-AZ/django/README.md b/az-AZ/django/README.md new file mode 100644 index 00000000000..8c8e4236afe --- /dev/null +++ b/az-AZ/django/README.md @@ -0,0 +1,27 @@ +# Django nədir? + +Django Python-da yazılmış ödənişsiz və açıq qaynaqlı internet tətbiq freymvörküdür. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/az-AZ/django_admin/README.md b/az-AZ/django_admin/README.md new file mode 100644 index 00000000000..156eae05654 --- /dev/null +++ b/az-AZ/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/az-AZ/django_forms/README.md b/az-AZ/django_forms/README.md new file mode 100644 index 00000000000..68676f99fa5 --- /dev/null +++ b/az-AZ/django_forms/README.md @@ -0,0 +1,479 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Security + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/az-AZ/django_installation/README.md b/az-AZ/django_installation/README.md new file mode 100644 index 00000000000..9b024008342 --- /dev/null +++ b/az-AZ/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/az-AZ/django_installation/instructions.md b/az-AZ/django_installation/instructions.md new file mode 100644 index 00000000000..f654aae7361 --- /dev/null +++ b/az-AZ/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual mühit(Virtual environment) + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Virtualenv ilə işləmək + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/az-AZ/django_models/README.md b/az-AZ/django_models/README.md new file mode 100644 index 00000000000..f2a68a8727f --- /dev/null +++ b/az-AZ/django_models/README.md @@ -0,0 +1,201 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/az-AZ/django_orm/README.md b/az-AZ/django_orm/README.md new file mode 100644 index 00000000000..ffe309bd81e --- /dev/null +++ b/az-AZ/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/az-AZ/django_start_project/README.md b/az-AZ/django_start_project/README.md new file mode 100644 index 00000000000..3767c62e17f --- /dev/null +++ b/az-AZ/django_start_project/README.md @@ -0,0 +1,260 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/az-AZ/django_templates/README.md b/az-AZ/django_templates/README.md new file mode 100644 index 00000000000..db2d20c4d4e --- /dev/null +++ b/az-AZ/django_templates/README.md @@ -0,0 +1,108 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/az-AZ/django_urls/README.md b/az-AZ/django_urls/README.md new file mode 100644 index 00000000000..d37a5e3c2fd --- /dev/null +++ b/az-AZ/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/az-AZ/django_views/README.md b/az-AZ/django_views/README.md new file mode 100644 index 00000000000..ab271e0914f --- /dev/null +++ b/az-AZ/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/az-AZ/dynamic_data_in_templates/README.md b/az-AZ/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..5a6ef017adf --- /dev/null +++ b/az-AZ/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/az-AZ/extend_your_application/README.md b/az-AZ/extend_your_application/README.md new file mode 100644 index 00000000000..c70a2db97ff --- /dev/null +++ b/az-AZ/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/az-AZ/how_the_internet_works/README.md b/az-AZ/how_the_internet_works/README.md new file mode 100644 index 00000000000..7b2c014c292 --- /dev/null +++ b/az-AZ/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![Figure 1.2](images/internet_3.png) + +It is fascinating, isn't it? But 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - you send messages and you expect some response. 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 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, 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 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! \ No newline at end of file diff --git a/az-AZ/html/README.md b/az-AZ/html/README.md new file mode 100644 index 00000000000..27c81ea68be --- /dev/null +++ b/az-AZ/html/README.md @@ -0,0 +1,227 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is 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 `TemplateDoesNotExist`, try to restart your server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +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 line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to GitHub + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% 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. + +{% 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: + +{% 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 %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/az-AZ/installation/README.md b/az-AZ/installation/README.md new file mode 100644 index 00000000000..b97592acbe8 --- /dev/null +++ b/az-AZ/installation/README.md @@ -0,0 +1,68 @@ +# 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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. + +Good luck! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Installation + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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. \ No newline at end of file diff --git a/az-AZ/intro_to_command_line/README.md b/az-AZ/intro_to_command_line/README.md new file mode 100644 index 00000000000..b95191c95c8 --- /dev/null +++ b/az-AZ/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Your first command (YAY!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/az-AZ/intro_to_command_line/open_instructions.md b/az-AZ/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/az-AZ/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/az-AZ/python_installation/README.md b/az-AZ/python_installation/README.md new file mode 100644 index 00000000000..8470b71f1f4 --- /dev/null +++ b/az-AZ/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/az-AZ/python_installation/instructions.md b/az-AZ/python_installation/instructions.md new file mode 100644 index 00000000000..592aafe0b5d --- /dev/null +++ b/az-AZ/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 the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/az-AZ/python_introduction/README.md b/az-AZ/python_introduction/README.md new file mode 100644 index 00000000000..6b66f8b55c6 --- /dev/null +++ b/az-AZ/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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. + +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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, type the `exit()` function + +{% 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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/az-AZ/template_extending/README.md b/az-AZ/template_extending/README.md new file mode 100644 index 00000000000..7f3697b7fd4 --- /dev/null +++ b/az-AZ/template_extending/README.md @@ -0,0 +1,151 @@ +# Template extending + +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. + +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 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 + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/az-AZ/whats_next/README.md b/az-AZ/whats_next/README.md new file mode 100644 index 00000000000..97c41870d93 --- /dev/null +++ b/az-AZ/whats_next/README.md @@ -0,0 +1,43 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](https://twitter.com/djangogirls) to stay up to date. + +### Can you recommend any further resources? + +Yes! There are a *lot* of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. + +#### Django + +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS and JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! \ No newline at end of file diff --git a/az/GLOSSARY.md b/az/GLOSSARY.md new file mode 100644 index 00000000000..5f7452b317e --- /dev/null +++ b/az/GLOSSARY.md @@ -0,0 +1,3 @@ +# kod redaktoru + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/az/README.md b/az/README.md new file mode 100644 index 00000000000..01736ae0502 --- /dev/null +++ b/az/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) + +## Introduction + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/az/SUMMARY.md b/az/SUMMARY.md new file mode 100644 index 00000000000..c5543050c28 --- /dev/null +++ b/az/SUMMARY.md @@ -0,0 +1,27 @@ +# Summary + +* [Introduction](README.md) +* [Installation](installation/README.md) +* [Installation (chromebook)](chromebook_setup/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) +* [Kod redaktoru](code_editor/README.md) +* [Introduction to Python](python_introduction/README.md) +* [What is Django?](django/README.md) +* [Django installation](django_installation/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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/az/chromebook_setup/README.md b/az/chromebook_setup/README.md new file mode 100644 index 00000000000..03285106dfd --- /dev/null +++ b/az/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook qurulumu + +> **Not: **Yükləmə addımlarını tamamlamısınızsa, bunu yenidən etməyə ehtiyyac yoxdur. Birbaşa [Python-a Giriş](../python_introduction/README.md) qisminə keçə bilərsiniz. + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/az/chromebook_setup/instructions.md b/az/chromebook_setup/instructions.md new file mode 100644 index 00000000000..1b15cbaf97d --- /dev/null +++ b/az/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +Əgər Chromebook istifadə etmirsinizsə, [bu hissəni birbaşa keçə bilərsiniz.](http://tutorial.djangogirls.org/en/installation/#install-python) İstifadə edirsinizsə, qurulum biraz fərqli olacaq. 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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/az/code_editor/README.md b/az/code_editor/README.md new file mode 100644 index 00000000000..da9d77ccdc2 --- /dev/null +++ b/az/code_editor/README.md @@ -0,0 +1,11 @@ +# Kod redaktoru + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +Siz kodunuzun birinci sətrini yazmağa balamaq üzrəsiniz, odur ki, kod redaktoru yükləmək vaxtıdır! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/az/code_editor/instructions.md b/az/code_editor/instructions.md new file mode 100644 index 00000000000..fcaa89b9015 --- /dev/null +++ b/az/code_editor/instructions.md @@ -0,0 +1,31 @@ +Çoxlu müxtəlif editor proqramları (düzənləyici) var və hansını istifadə etmək şəxsi seçimdən asılıdır. Əksər Python proqramçıları qarışıq, amma çox güclü IDE(inteqrallaşdırılmış (birləşdirilmiş) proqramlaşdırma mühiti)-lərdən istifadə edir, məsələn PyCharm kimi. Lakin yeni başlayanlar üçün bu bir qədər az əlverişlidir. Bizim tövsiyə etdiklərimiz isə eyni dərəcədə güclü, amma çox daha sadədır. + +Bizim tövsiyyələrimiz aşağıdakılardır, amma öz müəlliminizdən də soruşa bilərsiniz. + +## Gedit + +Gedit açıq-qaynaq, ödənişsiz, bütün əməliyyat sistemlərini dəstəkləyən editordur. + +[Buradan yükləyin](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[Buradan yükləyin](https://www.sublimetext.com/3) + +## Atom + +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. + +[Buradan yükləyin](https://atom.io/) + +## Biz nəyə görə kod editor quraşdırırıq? + +Sizə maraqlı gələ bilər ki, biz nəyə görə Word yaxud Notepad istifadə etmək yerinə bu xüsusi kod editor proqramı quraşdırırıq. + +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. :) \ No newline at end of file diff --git a/az/css/README.md b/az/css/README.md new file mode 100644 index 00000000000..fa7a6036195 --- /dev/null +++ b/az/css/README.md @@ -0,0 +1,304 @@ +# CSS – make it pretty! + +Bizim blogumuz hələ də son dərəcə eybəcər görünür, hə? Onu gözəlləşdirmək vaxtıdır. Biz bunun üçün CSS istifadə edəcəyik. + +## CSS nədir? + +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? Once more, we'll use something that programmers released on the Internet for free. Reinventing the wheel is no fun, you know. + +## Gəlin Bootstrap istifadə edək! + +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. Now it's developed by volunteers from all over the world! + +## Bootstrapı Quraşdır + +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! + +![Figure 14.1](images/bootstrap1.png) + +Artıq çox gözəl görünür! + +## Django-da statik sənələr + +Nəhayət, biz **static files** adlandırılan sənədlərə daha yaxından baxacağıq. 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. + +### Statik sənədləri (<0>static files) Djangoda hara yerləşdirək + +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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +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. 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 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 + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +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. :) 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 be overriden by 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 %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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 + +``` + +And now add a class `post` to your `div` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/az/deploy/README.md b/az/deploy/README.md new file mode 100644 index 00000000000..b44e2eaaf73 --- /dev/null +++ b/az/deploy/README.md @@ -0,0 +1,260 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ 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) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. + +Hit **Save** and then go back to the **Web** tab. + +We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. + +## Debugging tips + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: + +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. + +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. + +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? + +- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. + +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +And remember, your coach is here to help! + +# You are live! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! \ No newline at end of file diff --git a/az/deploy/install_git.md b/az/deploy/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/az/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/az/deploy/signup_pythonanywhere.md b/az/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/az/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/az/django/README.md b/az/django/README.md new file mode 100644 index 00000000000..c62c145305b --- /dev/null +++ b/az/django/README.md @@ -0,0 +1,27 @@ +# What is Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +Of course, the description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will simply start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/az/django_admin/README.md b/az/django_admin/README.md new file mode 100644 index 00000000000..46a5afbb500 --- /dev/null +++ b/az/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/az/django_forms/README.md b/az/django_forms/README.md new file mode 100644 index 00000000000..1d9efebffe4 --- /dev/null +++ b/az/django_forms/README.md @@ -0,0 +1,447 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? + +## URL + +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```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` we add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## Security + +Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to Github: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/az/django_installation/README.md b/az/django_installation/README.md new file mode 100644 index 00000000000..7834993e063 --- /dev/null +++ b/az/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/az/django_installation/instructions.md b/az/django_installation/instructions.md new file mode 100644 index 00000000000..0bc080f7055 --- /dev/null +++ b/az/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/az/django_models/README.md b/az/django_models/README.md new file mode 100644 index 00000000000..7aa11d11732 --- /dev/null +++ b/az/django_models/README.md @@ -0,0 +1,199 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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 + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/az/django_orm/README.md b/az/django_orm/README.md new file mode 100644 index 00000000000..31c47f27764 --- /dev/null +++ b/az/django_orm/README.md @@ -0,0 +1,218 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Chaining QuerySets + +You can also combine QuerySets by **chaining** them together: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/az/django_start_project/README.md b/az/django_start_project/README.md new file mode 100644 index 00000000000..fe1abc7ca9a --- /dev/null +++ b/az/django_start_project/README.md @@ -0,0 +1,202 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![It worked!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/az/django_templates/README.md b/az/django_templates/README.md new file mode 100644 index 00000000000..263eb1fd835 --- /dev/null +++ b/az/django_templates/README.md @@ -0,0 +1,106 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/az/django_urls/README.md b/az/django_urls/README.md new file mode 100644 index 00000000000..c491b27de5c --- /dev/null +++ b/az/django_urls/README.md @@ -0,0 +1,129 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![Url](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Regex + +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. + +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: + +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern + +Anything else in the URL definition will be taken literally. + +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. + +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: + +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/az/django_views/README.md b/az/django_views/README.md new file mode 100644 index 00000000000..07afe091a52 --- /dev/null +++ b/az/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/az/dynamic_data_in_templates/README.md b/az/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..807bb666ebc --- /dev/null +++ b/az/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/az/extend_your_application/README.md b/az/extend_your_application/README.md new file mode 100644 index 00000000000..0bae760be7c --- /dev/null +++ b/az/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: + +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? Of course: adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`. + +It will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ 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 %} + +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 --all . + $ git status + $ 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/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/az/how_the_internet_works/README.md b/az/how_the_internet_works/README.md new file mode 100644 index 00000000000..efd95c3f4b2 --- /dev/null +++ b/az/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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. + +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![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 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - 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 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, 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 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! \ No newline at end of file diff --git a/az/html/README.md b/az/html/README.md new file mode 100644 index 00000000000..004985089c2 --- /dev/null +++ b/az/html/README.md @@ -0,0 +1,213 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Add the following to your template file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +

Hi there!

+

It works!

+ +``` + +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 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `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, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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.

+
+ + +``` + +We've created three `div` sections here. + +* 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to Github + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% 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: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **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): + +{% 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. + +{% 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: + +{% 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 + $ git pull + [...] + + +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. + +* 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. :) \ No newline at end of file diff --git a/az/install_git.md b/az/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/az/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/az/installation/README.md b/az/installation/README.md new file mode 100644 index 00000000000..a7c627136c8 --- /dev/null +++ b/az/installation/README.md @@ -0,0 +1,58 @@ +# 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 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. \ No newline at end of file diff --git a/az/instructions.md b/az/instructions.md new file mode 100644 index 00000000000..30bd493b11b --- /dev/null +++ b/az/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/az/intro_to_command_line/README.md b/az/intro_to_command_line/README.md new file mode 100644 index 00000000000..5fb6d48dd1f --- /dev/null +++ b/az/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +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. :) + +> 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 by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/az/python_installation/README.md b/az/python_installation/README.md new file mode 100644 index 00000000000..93f81cb42d9 --- /dev/null +++ b/az/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/az/python_installation/instructions.md b/az/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/az/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/az/python_introduction/README.md b/az/python_introduction/README.md new file mode 100644 index 00000000000..c1642302532 --- /dev/null +++ b/az/python_introduction/README.md @@ -0,0 +1,1062 @@ +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.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. + +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. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, simply type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% 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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% 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! + +{% 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% 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 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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 + +{% 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!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/az/signup_pythonanywhere.md b/az/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/az/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/az/template_extending/README.md b/az/template_extending/README.md new file mode 100644 index 00000000000..35997f913d3 --- /dev/null +++ b/az/template_extending/README.md @@ -0,0 +1,147 @@ +# Template extending + +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. + +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 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 + + +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 %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. 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' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/az/whats_next/README.md b/az/whats_next/README.md new file mode 100644 index 00000000000..fbb1d2a7d6e --- /dev/null +++ b/az/whats_next/README.md @@ -0,0 +1,25 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](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](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). + +Later on, you can try the resources listed below. They're all very recommended! + +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/bg-BG/GLOSSARY.md b/bg-BG/GLOSSARY.md new file mode 100644 index 00000000000..e066787b75e --- /dev/null +++ b/bg-BG/GLOSSARY.md @@ -0,0 +1,3 @@ +# редактор на код + +Редакторът на код е приложение, което ти позволява да съхраняваш своя код за да можеш да продължиш с него по-късно. Може да научиш къде да намериш един от [главата Редактор на код](./code_editor/README.md) \ No newline at end of file diff --git a/bg-BG/README.md b/bg-BG/README.md new file mode 100644 index 00000000000..c6d374c37b3 --- /dev/null +++ b/bg-BG/README.md @@ -0,0 +1,51 @@ +# Django Girls ръководство + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> Тази работа е лицензирана под Creative Commons Attribution-ShareAlike 4.0 International License. За да видите копие на този лиценз, посетете https://creativecommons.org/licenses/by-sa/4.0/ + +## Добре дошли + +Добре дошли в ръководството на Django Girls! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Въведение + +Чувстваше ли някога, че светът все повече е свързан с технологиите, а ти оставаш в сянка? Мислеше как да създадеш уеб-сайт, но никога нямаше достатъчно мотивация да започнеш? Струвало ли ти се, че светът на софтуера е прекалено труден за теб да започнеш да правиш нещо сама? + +Имаме добра новина за теб! Програмирането не е толкова трудно, колкото изглежда, и ние искаме да ти покажем колко забавно може да бъде то. + +Това ръководство няма магически да те превърне в програмист. Ако искаш да си добра ще ти трябват месеци или даже години учене и упражняване. Но ние искаме да покажем, че програмирането или създаването на уебсайтове не е толкова сложно, колкото изглежда. Ще се постараем да обясним в детайли, колкото се може по-добре, за да не се чувстваш уплашена от технологиите. + +Надяваме се да те накараме да заобичаш технологиите толкова, колкото и ние ги обичаме! + +## Какво ще научиш от това ръководство? + +След като приключиш с ръководството, ще имаш малко работещо уеб-приложение: твоя собствен блог. Ще ти покажем как да го пуснеш в мрежата, така че другите да ти видят работата! + +Това ще изглежда (горе-долу) ето така: + +![Фигура 0.1](images/application.png) + +> Ако работиш с ръководството сам, и нямаш инструктор който да ти помага в случай на някой проблем, имаме чат система за теб: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). Помолихме нашите инструктори и миналите участници да са там от време на време и да помагат на другите с ръководството! Не се страхувай да задаваш въпроси там! + +Добре, [хайде да започнем от начало...](./how_the_internet_works/README.md) + +## Следвайки ръководството вкъщи + +Изумително е да си част от занятията на Django Girls, но също разбираме, че не винаги е възможно да присъстваш. Затова ние те насърчаваме да пробваш да следиш ръководството вкъщи. За читатели у дома, понастоящем приготвяме видеа, които ще улеснят следването на ръководството на вас. Проектът все още е в процес на обработка, но все повече и повече неща ще бъдат разгледани скоро на [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) YouTube канал. + +Във всяка вече покрита глава има линк, препращащ към правилното видео. + +## Относно и допринасяне + +Това ръководство е поддържано от [Django Girls](https://djangogirls.org/). Ако намериш някакви грешки или искаш да актуализираш ръководството, моля, [следвай насоките за допринасяне](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## Би ли искала да ни помогнеш да преведем ръководството на друг език? + +Понастоящем, преводите се съхраняват на платформата crowdin.com по този адрес: + +https://crowdin.com/project/django-girls-tutorial + +Ако твоят език не е изброен на [crowdin](https://crowdin.com/), моля [оставете заявка](https://github.com/DjangoGirls/tutorial/issues/new), информирайки ни за езика, за да можем да го добавим. \ No newline at end of file diff --git a/bg-BG/SUMMARY.md b/bg-BG/SUMMARY.md new file mode 100644 index 00000000000..7bba63767d5 --- /dev/null +++ b/bg-BG/SUMMARY.md @@ -0,0 +1,35 @@ +# Обобщение + +* [Въведение](README.md) +* [Инсталиране](installation/README.md) + * [Команден ред](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Редактор на код](installation/README.md#code-editor) + * [Виртуална среда](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Инсталиране (Chromebook)](chromebook_setup/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 URL адреси](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) \ No newline at end of file diff --git a/bg-BG/chromebook_setup/README.md b/bg-BG/chromebook_setup/README.md new file mode 100644 index 00000000000..f6e4ee94c21 --- /dev/null +++ b/bg-BG/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Настройка на Chromebook + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/bg-BG/chromebook_setup/instructions.md b/bg-BG/chromebook_setup/instructions.md new file mode 100644 index 00000000000..634a1224600 --- /dev/null +++ b/bg-BG/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Можеш да [пропуснеш този раздел](http://tutorial.djangogirls.org/en/installation/#install-python), ако не използваш Chromebook. Ако използваш, опитът ти в инсталацията ще бъде малко по-различен. Можеш да игнорираш останалата част от инструкциите за инсталиране. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Облачна IDE е инструмент, която ти дава редактор на код и достъп до компютър, работещ в Интернет, където можеш да инсталираш, да пишеш и да пускаш софтуер. За продължителността на ръководството, облачната IDE ще ти служи като твоя *локална машина*. Все пак ще пишеш команди в терминал, също като твоите съученици на OS X, Ubuntu или Windows, но твоят терминал ще бъде свързан с компютър, работещ някъде другаде, който облачната IDE настройва за теб. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). Можеш да избереш един от облачни IDE интерфейси и да следваш инструкциите за тази облачна IDE. + +#### PaizaCloud Cloud IDE + +1. Отиди на [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Направи акаунт +3. Натисни *New Server* и избери приложението Django +4. Натисни бутон на Терминал (от лявата страна на прозореца) + +Сега трябва да виждаш интерфейс със странична лента, бутоните са отляво. Натисни бутона "Terminal" за да се отвори ето такава подкана: + +{% filename %}Terminal{% endfilename %} + + $ + + +Терминалът на PaizaCloud Cloud IDE е готов за твоите инструции. Можеш да увеличиш прозореца за да го направиш малко по-голям. + +#### AWS Cloud9 + +Понастоящем, Cloud 9 изисква от теб да се регистрираш с AWS и да въведеш информация за кредитната си карта. + +1. Инсталирай Cloud 9 от [Chrome web store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Отиди на [c9.io](https://c9.io) и натисни *Get started with AWS Cloud9* +3. Регистрирай се за AWS акаунт (изисква информация за кредитна карта, но можеш да го използваш безплатно) +4. В AWS Dashboard, напиши *Cloud9* в лентата за търсене и я натисни +5. В Cloud 9 таблото, натисни *Create environment* +6. Наречи го *django-girls* +7. Конфигурирайки настройките, избери *Create a new instance for environment (EC2)* за "Environment Type" и *t2.micro* "Instance type" (трябва да пише "Free-tier eligible."). Настройката за икономия на разходи по подразбиране е наред и можеш да запазиш останалите по подразбиране. +8. Натисни *Next step* +9. Натисни *Create environment* + +Сега трябва да видиш интерфейс със странична лента, голям основен прозорец с малко текст и малък прозорец в долната част, който да изглежда като нещо подобно: + +{% filename %}bash{% endfilename %} + + yourusername:~/workspace $ + + +Тази долна зона е твоят терминал. Можеш да използваш терминала за изпращане на инструкции до отдалечения компютър Cloud 9. Можеш да промениш размера на прозореца, за да го направиш малко по-голям. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### Виртуална среда + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/bg-BG/code_editor/README.md b/bg-BG/code_editor/README.md new file mode 100644 index 00000000000..9d3b5025765 --- /dev/null +++ b/bg-BG/code_editor/README.md @@ -0,0 +1,11 @@ +# Редактор на код + +> За читателите у дома: тази глава е разгледана във видеото [Инсталиране на Python & Редактор на код](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s). + +На път си да напишеш първия си ред на код, така че е време да изтеглиш редактор на код! + +> **Забележка** Ако използваш Chromebook, пропусни тази глава и се увери, че следваш инструкциите [Настройка на Chromebook](../chromebook_setup/README.md). Облачната IDE, която си избрала (PaizaCloud Cloud IDE или AWS Cloud9) включва редактор на код и когато отвориш файл във твоята IDE от менюто File, автоматично ще използваш редактора. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/bg-BG/code_editor/instructions.md b/bg-BG/code_editor/instructions.md new file mode 100644 index 00000000000..b9ac32e5ccf --- /dev/null +++ b/bg-BG/code_editor/instructions.md @@ -0,0 +1,37 @@ +Има много различни редактори и това до голяма степен се свежда до личните предпочитания. Повечето програмисти на Python използват сложни, но изключително мощни IDE (интегрирани среди за разработка), като PyCharm. Като начинаещ обаче това вероятно е по-малко подходящо; нашите препоръки са еднакво мощни, но много по-прости. + +Нашите предложения са по-долу, но не се колебай да попиташ ментора си какви са техните предпочитания - по-лесно ще получиш помощ от тях. + +## Visual Studio Code + +Visual Studio Code е редактор на изходен код, разработен от Microsoft за Windows, Linux и macOS. Той включва поддръжка за отстраняване на грешки, вграден Git контрол, подчертаване на синтаксис, интелигентно попълване на код, фрагменти и рефакторинг на код. + +[Изтегли го тук](https://code.visualstudio.com/) + +## Gedit + +Gedit е безплатен редактор с отворен код, достъпен за всички операционни системи. + +[Изтегли го тук](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text е много популярен редактор на код с безплатен период за оценка и е достъпен за всички операционни системи. + +[Изтегли го тук](https://www.sublimetext.com/3) + +## Atom + +Atom е друг популярен редактор. Той е безплатен, с отворен код и се предлага за Windows, OS X и Linux. Atom е разработен от [GitHub](https://github.com/). + +[Изтегли го тук](https://atom.io/) + +## Защо инсталираме редактор на код? + +Може би се чудиш защо инсталираме този специален софтуер за редактиране на код, вместо да използваме нещо като Word или Notepad. + +Първата причина е, че кодът трябва да бъде **обикновен текст**, а проблемът с програми като Word и Textedit е, че те всъщност не произвеждат обикновен текст, те създават богат текст (с шрифтове и форматиране), използвайки персонализирани формати като [RTF (формат на обогатен текст)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +Втората причина е, че редакторите на код са специализирани за редактиране на код, така че те могат да предоставят полезни функции като подчертаване на код с цвят според значението му или автоматично затваряне на кавички за теб. + +Ще видим всичко това в действие по-късно. Скоро ще помислиш за надеждния си стар редактор на код като за един от любимите си инструменти. :) \ No newline at end of file diff --git a/bg-BG/css/README.md b/bg-BG/css/README.md new file mode 100644 index 00000000000..e0dd41cb8a3 --- /dev/null +++ b/bg-BG/css/README.md @@ -0,0 +1,330 @@ +# CSS - направи го красиво! + +Блогът ни все още изглежда доста грозен, нали? Време е да го направиш хубав! За това ще използваме CSS. + +## Какво е CSS? + +Cascading Style Sheets (CSS) е език, използван за описание на външния вид и форматирането на уебсайт, написан на език за маркиране (като HTML). Отнасяй се към него като грим за нашата уеб страница. ;) + +Но не искаме отново да започнем от нулата, нали? Още веднъж ще използваме нещо, което програмистите пуснаха в интернет безплатно. Преосмислянето на колелото не е забавно. + +## Нека използваме Bootstrap! + +Bootstrap е една от най-популярните фреймуорки за HTML и CSS за разработване на красиви уебсайтове: https://getbootstrap.com/ + +Той е написан от програмисти, които са работили за Twitter. Сега той е разработен от доброволци от цял свят! + +## Инсталирай Bootstrap + +За да инсталираш Bootstrap, отвори твоя `.html` файл в редактора на кода и го добави в секцията ``: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Това не добавя никакви файлове към твоя проект. То просто сочи файлове, които съществуват в Интернет. Затова продължи напред, отвори уебсайта си и актуализирай страницата. Ето го! + +![Фигура 14.1](images/bootstrap1.png) + +Вече изглежда по-хубав! + +## Статични файлове в Django + +Накрая ще разгледаме по-подробно тези неща, които наричахме **статични файлове**. Статичните файлове са всички ваши CSS и изображения. Съдържанието им не зависи от контекста на заявката и ще бъде едно и също за всеки потребител. + +### Къде да сложа статични файлове за Django + +Django вече знае къде да намери статичните файлове за вграденото приложение "admin". Сега трябва да добавим статични файлове за нашето собствено приложение, `blog`. + +Правим това, като създаваме папка, наречена `static` в блог приложението: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │ └── templates + └── mysite + + +Django автоматично ще открива всички папки, наречени 'static', в която и да е от папките на вашите приложения. Тогава то ще може да използва тяхното съдържание като статични файлове. + +## Твоят първи CSS файл! + +Нека сега създадем CSS файл, за да добавим свой собствен стил към твоята уеб страница. Създай нова директория, наречена `css` във твоята `static` директория. След това създай нов файл, наречен `blog.css` вътре в тази директория `css`. Готова? + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +Време е да напишеш малко CSS! Отвори файла `blog/static/css/blog.css` в твоя редактор на код. + +Тук няма да навлизаме твърде дълбоко в персонализирането и научаването на CSS. Има препоръка за безплатен CSS курс в края на тази страница, ако искаш да научиш повече. + +Но нека направим поне малко. Може би бихме могли да променим цвета на заглавията ни? За да разберат цветовете, компютрите използват специални кодове. Тези кодове започват с `#`, последвани от 6 букви (A–F) и цифри (0–9). Например кодът за синьо е `#0000FF`. Можеш да намериш цветовите кодове за много от цветовете тук: http://www.colorpicker.com/. Можеш също така да използваш [предварително определени цветове](http://www.w3schools.com/colors/colors_names.asp), като `red` и `green`. + +Във твоя `blog/static/css/blog.css` файл трябва да добавиш следния код: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1 a` е CSS селектор. Това означава, че прилагаме стиловете си към всеки `a` елемент вътре в елемент `h1`; селекторът `h2 a` прави същото за елементи `h2`. Така че, когато имаме нещо като `

връзка

`, ще се прилага стилът `h1 a`. В този случай ние му казваме да промени цвета си на `#C25100`, което е тъмно оранжево. Или можеш да поставиш свой собствен цвят тук, но се увери, че той има добър контраст на бял фон! + +В CSS файл определяме стилове за елементи в HTML файла. Първият начин да идентифицираме елементите е с името на елемента. Може да ги запомниш като тагове от секцията HTML. Нещата като `a`, `h1` и `body` са примери за имена на елементи. Ние също така идентифицираме елементи по атрибут `class` или атрибут `id`. Class и id са имена, които сама даваш на елемента. Класовете определят групи от елементи, а идентификаторите сочат конкретни елементи. For example, you could identify the following element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +Можеш да прочететеш повече за [CSS селектори в w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +Трябва също така да кажем на нашия HTML шаблон, че добавихме някои CSS. Отвори файла `blog/templates/blog/post_list.html` в редактора на кода и добави този ред в самото начало: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +Тук просто зареждаме статични файлове. :) Между таговете `` и ``, след връзките към CSS файловете на Bootstrap, добави този ред: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Браузърът чете файловете в реда, в който са зададени, така че трябва да се уверим, че това е на правилното място. В противен случай кодът в нашия файл може да бъде отменен с кода във файлове Bootstrap. Току-що казахме на нашия шаблон къде се намира нашият CSS файл. + +Твоят файл сега трябва да изглежда така: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +ОК, запази файла и актуализирай сайта! + +![Фигура 14.2](images/color2.png) + +Добра работа! Може би също бихме искали да дадем на нашия уебсайт малко въздух и да увеличим полето от лявата страна? Нека опитаме това! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +Добави това към твоя CSS, запиши файла и виж как работи! + +![Фигура 14.3](images/margin2.png) + +Може би можем да персонализираме шрифта в заглавието ни? Постави това в твоя `` в `blog/templates/blog/post_list.html` файл: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Както и преди, провери поръчката и постави преди връзката към `blog/static/css/blog.css`. Този ред ще импортира шрифт, наречен *Lobster* от Google Fonts (https://www.google.com/fonts). + +Намери блока за деклариране `h1 a` (кодът между скобите `{` и `}`) в CSS файла `blog/static/css/blog.css`. Сега добави ред `font-family: 'Lobster';` между скобите и актуализирай страницата: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Фигура 14.3](images/font.png) + +Страхотно! + +Както бе споменато по-горе, CSS има концепция за класове. Те ви позволяват да назовете част от HTML кода и да приложите стилове само към тази част, без да засягате другите. Това може да бъде супер полезно! Може би имаш два div (от division, разделяне), които правят нещо различно (като заглавието и публикацията ти). Един клас може да ти помогне да ги накараш да изглеждат различно. + +Go ahead and name some parts of the HTML code. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Сега ще добавим декларационни блокове към различни селектори. Селектори, започващи с `.`, се отнасят за класове. Има много страхотни ръководства и обяснения за CSS в мрежата, които могат да ти помогнат да разбереш следния код. Засега го копирай и постави във твоя `blog/static/css/blog.css` файл: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +След това заобиколи HTML кода, който показва публикациите с декларации за класове. Замени това: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +в `blog/templates/blog/post_list.html` с това: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Запази тези файлове и актуализирай уебсайта си. + +![Фигура 14.4](images/final.png) + +Ура! Изглежда страхотно, нали? Виж кода, който току-що поставихме, за да намериш местата, където добавихме класове в HTML и ги използвахме в CSS. Къде би направила промяната, ако искаш датата да е тюркоазена? + +Не се страхувай да се поинтересуваш с този CSS малко и се опитай да промениш някои неща. Играта с CSS може да ти помогне да разбереш какво правят различните неща. Ако счупиш нещо, не се притеснявай - винаги можеш да го отмениш! + +Наистина препоръчваме да вземеш безплатните онлайн курсове "Basic HTML & HTML5" и "Basic CSS" на [freeCodeCamp](https://learn.freecodecamp.org/). Те могат да ти помогнат да научиш всичко за правенето на уебсайтовете ти по-красиви с HTML и CSS. + +Готова ли си за следващата глава?! :) \ No newline at end of file diff --git a/bg-BG/deploy/README.md b/bg-BG/deploy/README.md new file mode 100644 index 00000000000..1463edcbcc8 --- /dev/null +++ b/bg-BG/deploy/README.md @@ -0,0 +1,246 @@ +# Внедряване! + +> **Забележка** Следващата глава понякога може да бъде малко трудна за преминаване. Продължи и я завърши; внедряването е важна част от процеса на разработване на уебсайтове. Тази глава е поставена в средата на ръководството, така че твоят ментор да ти помогне с малко по-сложния процес на вдигане на уебсайта ти онлайн. Това означава, че все още можеш да завършиш ръководството самостоятелно, ако ти липсва време. + +Досега твоят уебсайт беше достъпен само на твоя компютър. Сега ще научите как да го прехвърлите в онлайн пространството! Разгръщането е процесът на публикуване на приложението ви в Интернет, така че хората най-накрая да могат да отидат и да видят приложението ви. :) + +Както научихте, уебсайт трябва да бъде разположен на сървър. В интернет има много доставчици на сървъри, ще използваме [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere е безплатен за малки приложения, които нямат твърде много посетители, така че определено засега ще ви бъде достатъчно. + +Другата външна услуга, която ще използваме е [GitHub](https://www.github.com), която е услуга за хостинг на код. Има и други, но почти всички програмисти имат GitHub акаунт в наши дни, а сега и вие! + +Тези три места ще бъдат важни за вас. Вашият локален компютър ще бъде мястото, където правите разработка и тестване. Когато сте доволни от промените, ще поставите копие на програмата си в GitHub. Вашият уебсайт ще бъде на PythonAnywhere и ще го актуализирате, като получите ново копие на вашия код от GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Стартираме нашето Git хранилище + +Git проследява промените в определен набор от файлове в т.нар. склад (или за кратко "репо"). Нека започнем еднo за нашия проект. Отворете конзолата и стартирайте тези команди в директорията `djangogirls`: + +> **Забележка** Проверете текущата си работна директория с команда `pwd` (Mac OS X / Linux) или `cd` (Windows), преди да инициализирате хранилището. Трябва да сте в папката `djangogirls`. + +{% filename %}command-line{% endfilename %} + + $ 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` в основната директория. Отворете редактора си и създайте нов файл със следното съдържание: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +И го запишете като `.gitignore` в папката "djangogirls". + +> **Забележка** Точката в началото на името на файла е важна! Ако имате проблеми с създаването му (Macs не харесва да създавате файлове, които започват с точка чрез Finder, например), след това използвайте функцията "Save As" в редактора си; това е бронеустойчиво. И не забравяйте да добавите `.txt`, `.py` или друго разширение към името на файла - той ще бъде разпознат от Git само ако името е просто `.gitignore`. Linux и MacOS взимат файловете с име, което започва с `.` (като `.gitignore`) за скрити и нормалната команда `ls` няма да показва тези файлове. Вместо това използвайте `ls -a`, за да видите файла `.gitignore`. +> +> **Забележка** Един от файловете, които сте посочили във вашия `.gitignore` файл е `db.sqlite3`. Този файл е вашата локална база данни, където се съхраняват всички ваши потребители и публикации. Ще следваме стандартната практика за уеб програмиране, което означава, че ще използваме отделни бази данни за вашия локален тестващ сайт и вашия уеб сайт на живо в PythonAnywhere. Базата данни на PythonAnywhere може да бъде SQLite, като вашата разработваща машина, но обикновено ще използвате такава, наречена MySQL, която може да се справи с много повече посетители на сайта, отколкото SQLite. Така или иначе, като игнорирате вашата SQLite база данни за копието на GitHub, това означава, че всички публикувани досега публикации и superuser ще бъдат достъпни само локално и ще трябва да създавате нови в производството. Трябва да мислите за вашата локална база данни като за добра площадка, където можете да тествате различни неща и да не се страхувате, че ще изтриете истинските си публикации от блога. + +Добра идея е да използвате команда `git status` преди `git add` или винаги, когато се окажете несигурни какво се е променило. Това ще ви помогне да предотвратите появата на изненади, като например добавяне или поемане на грешни файлове. Командата `git status` връща информация за всички непроследени/модифицирани/поетапни файлове, състоянието на клона и много други. Изходът трябва да бъде подобен на следното: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +И накрая спестяваме промените си. Отидете на конзолата си и изпълнете следните команди: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ 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](https://www.github.com) и се регистрирайте за нов безплатен потребителски акаунт. (Ако вече сте го направили в подготвителната работилница, това е чудесно!) Не забравяйте да запомните паролата си (добавете я към вашия мениджър на пароли, ако използвате такъв). + +След това създайте ново хранилище, като му дадете името "my-first-blog". Оставете квадратчето за „инициализация с README“ отместено, оставете опцията .gitignore празна (направихме това ръчно) и оставете лиценза като None. + +![](images/new_github_repo.png) + +> **Забележка** Името `my-first-blog` е важно - бихте могли да изберете нещо друго, но това ще се случва много пъти в инструкциите по-долу и ще трябва да го замествате всеки път. Вероятно е по-лесно да се придържаме към името `my-first-blog`. + +На следващия екран ще се покаже URL за клониране на вашия склад, което ще използвате в някои от следващите команди: + +![](images/github_get_repo_url_screenshot.png) + +Сега трябва да свържем Git хранилището на вашия компютър към това в GitHub. + +Въведете следното в конзолата си (заменете `` с потребителското име, което сте въвели, когато сте създали акаунта си в GitHub, но без скобите - URL адресът трябва да съответства на клонирания URL адрес, който току-що видяхте): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Когато избутате кода към GitHub, ще бъдете попитани за вашето потребителско име и парола за GitHub (било то в прозореца на командния ред или в изскачащ прозорец), а след въвеждане на идентификационните данни трябва да видите нещо подобно: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Кодът ви вече е на GitHub. Отидете и го вижте! Ще откриете, че е в добра компания - [Django](https://github.com/django/django), [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial) и много други страхотни софтуерни проекти с отворен код също са домакини на кода си в GitHub. :) + +# Настройване на нашия блог на PythonAnywhere + +## Регистрирайте се за акаунт в PythonAnywhere + +> **Забележка** Може би вече сте създали акаунт в PythonAnywhere по-рано по време на стъпките за инсталиране - ако е така, няма нужда да го правите отново. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Конфигуриране на нашия сайт на PythonAnywhere + +Върнете се към главното табло [PythonAnywhere Dashboard](https://www.pythonanywhere.com/), като кликнете върху логото и изберете опцията за стартиране на конзола "Bash" - това е версията на командния ред PythonAnywhere, точно като тази на вашия компютър. + +![Секцията 'Нова конзола' в уеб интерфейса на PythonAnywhere, с бутон за 'bash'](images/pythonanywhere_bash_console.png) + +> **Забележка** PythonAnywhere е базиран на Linux, така че ако сте на Windows, конзолата ще изглежда малко по-различна от тази на вашия компютър. + +Внедряването на уеб приложение в PythonAnywhere включва сваляне на кода от GitHub и конфигуриране на PythonAnywhere да го разпознае и да започне да го обслужва като уеб приложение. Има ръчни начини за това, но PythonAnywhere предоставя помощен инструмент, който ще свърши всичко за вас. Нека го инсталираме първо: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +Това трябва да отпечата някои неща като `Collecting pythonanywhere` и в крайна сметка да завърши с ред, който казва `Successfully installed (...) pythonanywhere- (...)`. + +Сега стартираме помощника за автоматично конфигуриране на приложението ви от GitHub. Въведете следното в конзолата на PythonAnywhere (не забравяйте да използвате потребителското си име на GitHub вместо ``, така че URL адресът да съответства на клонираният URL от GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +Докато гледаш това да работи, ще можеш да видиш какво прави: + +- Изтегляне на вашия код от GitHub +- Създаване на virtualenv на PythonAnywhere, точно като този на вашия собствен компютър +- Актуализиране на вашия файл с настройки с някои настройки за внедряване +- Настройка на база данни на PythonAnywhere с помощта на командата `manage.py migrate` +- Настройка на статичните ви файлове (за тях ще научим по-късно) +- И конфигуриране на PythonAnywhere да обслужва вашето уеб приложение чрез неговия API + +На PythonAnywhere всички тези стъпки са автоматизирани, но те са същите стъпки, които би трябвало да преминете с всеки друг доставчик на сървъри. + +Основното, което трябва да забележите в момента, е, че вашата база данни в PythonAnywhere всъщност е напълно отделена от вашата база данни на вашия собствен компютър, така че може да има различни публикации и администраторски акаунти. В резултат на това, точно както направихме на вашия собствен компютър, трябва да инициализираме администраторския акаунт с `createsuperuser`. PythonAnywhere автоматично активира вашия virtualenv за вас, така че всичко, което трябва да направите, е да стартирате: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Въведете данните за вашия администратор потребител. Най-добре е да използвате същите, които използвате на собствения си компютър, за да избегнете объркване, освен ако не искате да направите паролата на PythonAnywhere по-сигурна. + +Сега, ако желаете, можете също да разгледате кода си на PythonAnywhere, като използвате `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +Можете също да отидете на страницата „Файлове“ и да се придвижвате наоколо, използвайки вградения файлов браузър на PythonAnywhere. (От страницата на конзолата можете да стигнете до други страници на PythonAnywhere от бутона на менюто в горния десен ъгъл. След като сте на една от страниците, има връзки към другите в горната част.) + +## Вече сте на живо! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Забележка** Това е ръководство за начинаещи и при разгръщането на този сайт взехме няколко преки пътища, които не са идеални от гледна точка на сигурността. Ако и когато решите да надградите този проект или да започнете нов проект, трябва да прегледате [контролния списък за разгръщане на Django](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) за някои съвети относно осигуряването на вашия сайт. + +## Съвети за отстраняване на грешки + +Ако видиш грешка при изпълнението на скрипта `pa_autoconfigure_django.py`, ето няколко често срещани причини: + +- Забравяйки да създадете своя маркер за API на PythonAnywhere API. +- Грешка в URL адреса ви в GitHub +- Ако видите грешка, която казва *"Could not find your settings.py"*, вероятно защото не успяхте да добавите всичките си файлове в Git и/или не ги избутахте до GitHub успешно. Погледнете още един път раздела Git по-горе +- Ако преди това сте се регистрирали за акаунт в PythonAnywhere и имате грешка с collectstatic, вероятно имате по-стара версия на SQLite (например 3.8.2) за вашия акаунт. В такъв случай се регистрирайте за нов акаунт и опитайте командите в секцията PythonAnywhere по-горе. + +Ако видите грешка, когато се опитвате да посетите вашия сайт, първото място за търсене на информация за отстраняване на грешки е във вашия **error log**. Ще намерите линк към това на страницата на PythonAnywhere ["Web"](https://www.pythonanywhere.com/web_app_setup/). Вижте дали има съобщения за грешки там; най-новите са най-отдолу. + +Също така има някои [общи съвети за отстраняване на грешки на помощния сайт на PythonAnywhere](http://help.pythonanywhere.com/pages/DebuggingImportError). + +И не забравяйте, че вашият ментор е тук, за да ви помогне! + +# Вижте вашия сайт! + +Страницата по подразбиране за вашия сайт трябва да гласи „It worked!“, точно както прави на вашия локален компютър. Опитайте да добавите `/admin/` в края на URL адреса и ще бъдете отведени до администраторския сайт. Влезте с потребителското име и паролата и ще видите, че можете да добавяте нови публикации на сървъра - не забравяйте, че публикациите от вашата локална база данни за тестове не бяха изпратени във вашия блог на живо. + +След като създадете няколко публикации, можете да се върнете към вашата локална настройка (не PythonAnywhere). От тук трябва да работите върху вашата локална настройка, за да направите промени. Това е често срещан работен процес в уеб разработката - правете промени локално, бутате тези промени в GitHub и изтегляте промените надолу към вашия уеб сървър на живо. Това ви позволява да работите и да експериментирате, без да нарушавате уеб сайта си на живо. Доста готино, а? + +Заслужавате *огромни* похвали! Сървърните внедрения са едни от най-трудните части на уеб разработката и често отнемат на хората няколко дни, преди да ги накарат да работят. Но вие имате своя сайт на живо, в реалния Интернет! \ No newline at end of file diff --git a/bg-BG/deploy/install_git.md b/bg-BG/deploy/install_git.md new file mode 100644 index 00000000000..5d78ab9ce57 --- /dev/null +++ b/bg-BG/deploy/install_git.md @@ -0,0 +1,52 @@ +Git е "система за контрол на версиите", използвана от много програмисти. Този софтуер може да проследява промените във файловете с течение на времето, така че да можете да заредите конкретни версии по-късно. Нещо като функцията „проследяване на промените“ в програми за текстообработка (например, Microsoft Word или LibreOffice Writer), но много по-мощна. + +## Инсталиране на Git + + + +Можете да свалите Git от [git-scm.com](https://git-scm.com/). Можеш да натиснеш „next“ на всички стъпки, с изключение на две: в стъпката, където се изисква да избереш твоя редактор, трябва да избереш Nano, и в стъпката, озаглавена „Настройка на вашата PATH среда“, избери "Използване на Git и незадължителни Unix инструменти от командния ред на Windows" (най-долната опция). Освен това, настройките по подразбиране са добре. Разгледайте Windows стил, Unix стил за окончанията на редовете е добре. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Свалете Git от [git-scm.com](https://git-scm.com/) и следвайте инструкцията. + +> **Забележка** Ако използвате OS X 10.6, 10.7 или 10.8, ще трябва да инсталирате версията на git от тук: [Инсталатор на Git за OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/bg-BG/deploy/signup_pythonanywhere.md b/bg-BG/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..007eba2cfe2 --- /dev/null +++ b/bg-BG/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere е услуга за ползване на Python код на сървъри „в облака“. Ще използваме нея за хостинг на нашия сайт, на живо и в интернет. + +Ще направим блог, който изграждаме на PythonAnywhere. Регистрирайте се за акаунт за начинаещи в PythonAnywhere (безплатното ниво е добре, нямате нужда от кредитна карта). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![Страницата за регистрация в PythonAnywhere показва бутон за създаване на безплатен акаунт за начинаещи](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Забележка** Когато избирате вашето потребителско име тук, имайте предвид, че URL адресът на вашия блог ще приеме формата `yourusername.pythonanywhere.com`, така че изберете свой собствен прякор или име на блога. Също така, запомнете вашата парола (добавете я към вашия мениджър на пароли, ако използвате такъв). + +## Създаване на PythonAnywhere API токен + +Това е нещо, което трябва да направите само веднъж. Когато се регистрирате за PythonAnywhere, ще бъдете отведени до таблото си за управление. Намерете линка в горния десен ъгъл до страницата си „ Account“: + +![Връзка към акаунта в горния десен ъгъл на страницата](../deploy/images/pythonanywhere_account.png) + +след това изберете раздела, наречен "API token", и натиснете бутона с надпис "Create new API token". + +![Раздел на API токен на страницата „Акаунт“](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/bg-BG/django/README.md b/bg-BG/django/README.md new file mode 100644 index 00000000000..b6f4ebe0064 --- /dev/null +++ b/bg-BG/django/README.md @@ -0,0 +1,27 @@ +# Какво е Django? + +Django (/ ˈdʒæŋɡoʊ / *jang-goh*) е безплатна и отворена уеб рамка, написана на Python. Уеб рамката е набор от компоненти, които ви помагат да развивате уеб сайтове по-бързо и по-лесно. + +Когато създавате уебсайт, винаги се нуждаете от подобен набор от компоненти: начин за справяне с удостоверяването на потребителя (регистрация, влизане, излизане), панел за управление на вашия уебсайт, формуляри, начин за качване на файлове и т. н. + +За ваше щастие, други хора отдавна забелязаха, че уеб разработчиците са изправени пред подобни проблеми при изграждането на нов сайт, така че те се обединиха и създадоха рамки (Django е една от тях), които ви дават готови компоненти за използване. + +Рамките съществуват за да ви спестяват нуждата да преоткривате колелото и да помогнат за облекчаване на част от разходи, когато създавате нов сайт. + +## Защо имате нужда от рамка? + +За да разберем за какво всъщност е Django, трябва да разгледаме по-отблизо сървърите. Първото нещо е, че сървърът трябва да знае, че искате той да ви обслужва уеб страница. + +Представете си пощенска кутия (порт), която се следи за входящи писма (заявки). Това се прави от уеб сървър. Уеб сървърът чете писмото и след това изпраща отговор с уеб страница. Но когато искате да изпратите нещо, трябва да имате някакво съдържание. А Django е нещо, което ви помага да създавате съдържанието. + +## Какво се случва, когато някой поиска уебсайт от вашия сървър? + +Когато заявката стигне до уеб сървър, тя се предава на Django, който се опитва да разбере какво всъщност се иска. Първо взема адреса на уеб страница и се опитва да разбере какво да прави. Тази част се прави от **urlresolver** на Django (обърнете внимание, че адресът на уебсайт се нарича URL - Uniform Resource Locator - така че името *urlresolver* има смисъл). Не е много умно - взема списък от модели и се опитва да съответства на URL адреса. Django проверява шаблоните отгоре надолу и ако нещо съвпада, Django предава заявката на свързаната функция (която се нарича *view*). + +Представете си пощенски превозвач с писмо. Тя върви по улицата и проверява всеки домашен номер спрямо този на писмото. Ако съвпада, тя поставя писмото там. Ето как работи urlresolver! + +Във функцията *view* се правят всички интересни неща: можем да разгледаме база данни, за да потърсим някаква информация. Може би потребителят иска да промени нещо в данните? Като писмо, в което се казва: „Моля, променете описанието на моята работа“. *view* може да провери дали ви е позволено да го направите, след това актуализира описанието на работата за вас и изпраща обратно съобщение: „Готово!“ Тогава *view* генерира отговор и Django може да го изпрати до уеб браузъра на потребителя. + +Описанието по-горе е малко опростено, но все още не е необходимо да знаете всички технически неща. Наличието на обща идея е достатъчно. + +Така че вместо да се гмурнем твърде много в детайли, ще започнем да създаваме нещо с Django и ще научим всички важни части по пътя! \ No newline at end of file diff --git a/bg-BG/django_admin/README.md b/bg-BG/django_admin/README.md new file mode 100644 index 00000000000..6620805eda7 --- /dev/null +++ b/bg-BG/django_admin/README.md @@ -0,0 +1,57 @@ +# Администратор на Django + +За добавяне, редактиране и изтриване на публикациите, които току-що моделирахме, ще използваме администратора на Django. + +Нека отворим файла `blog/admin.py` в редактора на кода и заменим съдържанието му с това: + +{% filename %}blog/admin.py{% endfilename %} + +```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/. Ще видите страница за вход като тази: + +![Страница за вход](images/login_page2.png) + +За да влезете, трябва да създадете *superuser* - потребителски акаунт, който има контрол върху всичко в сайта. Върнете се в командния ред, напишете `python manage.py createsuperuser` и натиснете enter. + +> Не забравяйте, че за да пишете нови команди, докато уеб сървърът работи, отворете нов прозорец на терминала и активирайте своя virtualenv. Прегледахме как да пишете нови команди във **Вашия първи проект на Django!**, в секцията **Стартиране на уеб сървъра**. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +Когато бъдеш подканена, въведи потребителското си име (малки букви, без интервали), имейл адрес и парола. **Не се притеснявайте, че не можете да видите паролата, която въвеждате - така трябва да бъде.** Въведете я и натиснете `enter`, за да продължите. Резултатът трябва да изглежда така (където потребителското име и имейл трябва да са ваши собствени): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Върнете се в браузъра си. Влезте с избраните от вас име и парола на superuser; трябва да видите таблото за управление на Django. + +![Django администратор](images/django_admin3.png) + +Отидете на постове и експериментирайте малко с тях. Добавете пет или шест публикации в блога. Не се притеснявайте за съдържанието - вижда се само на вашия локален компютър - можете да копирате и поставите някакъв текст от това ръководство, за да спестите време. :) + +Уверете се, че поне две или три публикации (но не всички) имат зададена дата на публикуване. По-късно ще бъде полезно. + +![Django администратор](images/edit_post3.png) + +Ако искате да знаете повече за администратора на Django, трябва да проверите документацията на Django: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +Това вероятно е подходящ момент да вземете кафе (или чай) или нещо за хапване, за да се "заредите". Създадохте първия си модел Django - заслужавате малка почивка! \ No newline at end of file diff --git a/bg-BG/django_forms/README.md b/bg-BG/django_forms/README.md new file mode 100644 index 00000000000..487e7b6a043 --- /dev/null +++ b/bg-BG/django_forms/README.md @@ -0,0 +1,481 @@ +# Django форми + +Последното нещо, което искаме да направим в нашия уеб сайт е да създадем начин за добавяне и редактиране на публикации в блога. Django администратора е супер, но е по-трудно да се персонализира и направи приятно на външен вид. С формите ще имаме абсолютно надмощие над нашия изглед - можем да правим почти всичко което може да си представим! + +Хубавото на Django формите е, че може да дефинираме форма от самото начало или да създадем ModelForm, в която ще съхраняваме резултатът от формата на модела. + +Точно това искаме да направим: ще създадем форма за нашия `Post` модел. + +Като всяка важна част от Django, формите също имат собствен файл: `forms.py`. + +Трябва да създадем файл с това наименование в директорията на `blog`. + + blog + └── forms.py + + +И така, нека да отворим IDE и напишем следният код: + +{% filename %}blog/forms.py{% endfilename %} + +```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, view и template. + +## Връзка до страницата чрез формата + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new изглед + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Шаблон (Template) + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* Трябва да покажем формата. Можем да направим това чрез (например) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* Трябва ни бутон `Save`. Това правим с HTML button: ``. +* И най-накрая, точно след отварящия `
` tag трябва да добавим {% raw %}`{% csrf_token %}`{% endraw %}. Това е много важно, тъй като прави нашата форма надеждна! Ако забравите за това, Django ще се оплаче когато се опитате да запазите формата. + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Запазване на формата + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect + +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) + +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Проверка на формите (Form validation) + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Редактиране на формата + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Сигурност + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## Още едно нещо: време за deploy + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* Първо съхранете новия си код и го пратете към GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* След това в [PythonAnywhere Bash конзолата](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Накрая отидете на ["Web" страница](https://www.pythonanywhere.com/web_app_setup/), използвайте бутона от менюто в горният десен ъгъл на конзолата) и натиснете **Reload**. Опреснете блога си https://subdomain.pythonanywhere.com за да видите промените. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/bg-BG/django_installation/README.md b/bg-BG/django_installation/README.md new file mode 100644 index 00000000000..9af34473be4 --- /dev/null +++ b/bg-BG/django_installation/README.md @@ -0,0 +1,7 @@ +# Инсталиране на Django + +> **Забележка** Ако използвате Chromebook, пропуснете тази глава и се уверете, че следвате инструкциите [Настройка на Chromebook](../chromebook_setup/README.md). +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/bg-BG/django_installation/instructions.md b/bg-BG/django_installation/instructions.md new file mode 100644 index 00000000000..745b3163121 --- /dev/null +++ b/bg-BG/django_installation/instructions.md @@ -0,0 +1,231 @@ +> Част от този раздел е базирана на ръководства от Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Част от този раздел е базирана на [django-marcador ръководство](http://django-marcador.keimlink.de/) лицензиранo съгласно 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` е името на вашия логин). + +> **ЗАБЕЛЕЖКА:** В Windows се уверете, че тази директория не съдържа акцентирани или специални знаци; ако вашето потребителско име съдържа символи с ударение, използвайте друга директория, например, `C:\djangogirls`. + +За това ръководство ще използваме нова директория `djangogirls` от вашата домашна директория: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +Ще направим virtualenv, наречен `myvenv`. Общата команда ще бъде във формата: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +За да създадеш нов `virtualenv`, трябва да отвориш командния ред и да стартираш `python -m venv myvenv`. Ще изглежда така: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Където `myvenv` е името на вашата `virtualenv`. Можете да използвате всяко друго име, но се придържайте към малки букви и не използвайте интервали, ударения или специални знаци. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +Можем да създадем `virtualenv` и в Linux и OS X, като пуснем `python3 -m venv myvenv`. Ще изглежда така: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` е името на вашата `virtualenv`. Можете да използвате всяко друго име, но се придържайте към малки букви и не използвайте интервали. Също така е добре името да бъде кратко, понеже ще го използвате често! + +> **ЗАБЕЛЕЖКА:** В някои версии на Debian/Ubuntu може да получите следната грешка: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> В този случай следвайте инструкциите по-горе и инсталирайте пакета `python3-venv`: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **ЗАБЕЛЕЖКА:** При някои версии на Debian/Ubuntu инициирането на виртуалната среда като тази в момента дава следната грешка: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> За да заобиколите това, използвайте вместо това командата `virtualenv`. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **ЗАБЕЛЕЖКА:** Ако получите грешка като +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> вместо това стартирайте: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Работа с virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Стартирайте виртуалната си среда като напишете: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. В този случай трябва да отворите нов прозорец на PowerShell като изберете "Run as Administrator." След това напишете следната команда преди да стартирате виртуалната си среда: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Промяна при политиката на изпълнението +> Политиката на изпълнението ви предпазва от скриптове на които нямате доверие. При промяна на политиката на изпълнение може да бъдете изложени на опасен риск описан в темата about_Execution_Policies help в http://go.microsoft.com/fwlink/?LinkID=135170. Искате ли да промените политиката на изпълнението? [Y] ДА [A] Да на всичко [N] Не [L] Не на всичко [S] Прекрати [?] Помощ (по подразбиране е "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> Предимството е, че не е необходимо да сменяте между прозорците на IDE и командния ред. + + + + + +Стартирайте виртуалната си среда като напишете: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Помнете, че трябва да заместите `myvenv` с името на вашата избрана `virtualenv`. + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> +> + + + +Ще разбереш, че `virtualenv` е стартирана като видиш че подканата в конзолата ти започва с `(myvenv)`. + +Когато работите от виртуална среда, `python` автоматично ще се насочи към правилната версия, така че може да използвате команда `python` вместо `python3`. + +Добре, сега имаме всичкo необходимо на едно място. Най-накрая може да инсталираме Django! + +## Инсталиране на Django {#django} + +Сега след като имате стартирана `virtualenv` може да инсталирате Django. + +Преди да направим това обаче ще проверим дали имаме инсталирана последната версия на `pip`, софтуерът, който използваме да инсталираме Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + + +### Инсталиране на пакети с изисквания + +Файла съдържа лист от зависимости, които да се инсталират с командата `pip install`: + +Първо създайте файл с име `requirements.txt` в папка `djangogirls`, като използвате IDE инсталиран по-рано. Това става като отворите нов файл в редактора и след това го запазите като `requirements.txt` в папка `djangogirls/`. Вашата директория трябва да изглежда така: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +Във вашият `djangogirls/requirements.txt` файл трябва да добавите следното: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Сега напишете команда `pip install -r requirements.txt` за да инсталирате Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). Ако съдържа, моля помислете за друго място без разстояние, знак за ударение или други специални знаци (предложение: `C:\djangogirls`). Създайте нова виртуална среда в новата директория, след това изтрийте старата и опитайте отново командата. (Преместването на папката с виртуална среда няма да работи, тъй като виртуалната среда използва абсолютни пътеки.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> Ако получите грешка при извикване на pip при Ubuntu 12.04 напишете следната команда `python -m pip install -U --force-reinstall pip` за да оправите инсталацията на pip във виртуалната среда. + + + +Това е! Сега вече (най-накрая) сте готови да създадете Django апликация! \ No newline at end of file diff --git a/bg-BG/django_models/README.md b/bg-BG/django_models/README.md new file mode 100644 index 00000000000..85aed520255 --- /dev/null +++ b/bg-BG/django_models/README.md @@ -0,0 +1,201 @@ +# Модели на 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 model + +Знаейки какво е обект, можем да създадем модел на Django за нашата публикация в блога. + +Моделът в Django е специален вид обект - той се записва в `database`. База данни е съвкупност от данни. Това е място, на което ще съхранявате информация за потребители, публикации в блога си и т.н. Ще използваме база данни SQLite, за да съхраняваме нашите данни. Това е адаптерът за база данни Django по подразбиране - това ще ни бъде достатъчно в момента. + +Можете да мислите за модел в базата данни като електронна таблица с колони (полета) и редове (данни). + +### Създаване на приложение + +За да поддържаме всичко подредено, ние ще създадем отделно приложение вътре в нашия проект. Много е хубаво да се организира всичко от самото начало. За да създадем приложение, трябва да стартираме следната команда в конзолата (от директорията `djangogirls`, където е файлът ` manage.py`): + +{% filename %}Mac OS X и Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +Ще забележите, че се създава нова директория `blog` и сега съдържа редица файлове. Директориите и файловете в нашия проект трябва да изглеждат така: + + djangogirls + ├── blog + │ ├── admin.py + │ ├── apps.py + │ ├── __init__.py + │ ├── migrations + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │ ├── __init__.py + │ ├── settings.py + │ ├── urls.py + │ └── wsgi.py + ├── myvenv + │ └── ... + └── requirements.txt + + + +След създаването на приложение също трябва да кажем на Django, че трябва да го използва. Правим това във файла `mysite/settings.py` -- отваряме го във вашия редактор на кодове. Трябва да намерим `INSTALLED_APPS` и да добавим ред, съдържащ `'blog.apps.BlogConfig'`. Така че крайният продукт трябва да изглежда така: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Създаване на модел на блог публикация + +Във файла `blog/models.py` дефинираме всички обекти, наречени `Models` - това е място, на което ще дефинираме нашата публикация в блога. + +Нека да отворим `blog/models.py` в редактора на кода, да премахнем всичко от него и да напишем код така: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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` означава, че публикацията е модел на Django, така че Django знае, че трябва да бъде записана в базата данни. + +Сега дефинираме свойствата, за които говорихме: `title`, `text`, `created_date`, `published_date` и `author`. За целта трябва да определим типа на всяко поле (текст ли е? Число? Дата? Отношение към друг обект, като User?) + +- `models.CharField` -- по този начин определяте текст с ограничен брой знаци. +- `models.TextField` -- това е за дълъг текст без ограничение. Звучи идеално за съдържание в блог, нали? +- `models.DateTimeField` -- това е дата и час. +- `models.ForeignKey` -- това е връзка към друг модел. + +Тук няма да обясняваме всяка част от кода, тъй като това ще отнеме твърде много време. Трябва да разгледате документацията на Django, ако искате да знаете повече за моделните полета и как да дефинирате неща, различни от описаните по-горе (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field -types). + +Какво ще кажете за `def publish(self):`? Това е точно методът `publish`, за който говорихме преди. `def` означава, че това е функция/метод и `publish` е името на метода. Можете да промените името на метода, ако искате. Правилото за именуване е, че използваме малки букви и подчертавки вместо интервали (прасни места). Например метод, който изчислява средна цена, може да се нарече `calculate_average_price`. + +Методите често `връщат` нещо. Има пример за това в метода `__str__`. В този сценарий, когато извикаме `__str __ ()`, ще получим текст (**string**) със заглавие на публикацията. + +Също така забележете, че и двете `def publish(self):` и `def __str__(self):` са отредени в нашия клас. Тъй като Python е чувствителен към бялото пространство, трябва да отстъпим методите си вътре в класа. В противен случай методите няма да принадлежат към класа и можете да получите някакво неочаквано поведение. + +Ако нещо все още не е ясно за моделите, не се колебайте да попитате своя ментор! Знаем, че е сложно, особено когато научиш едновременно какво са обекти и функции. Но да се надяваме, че сега изглежда малко по-малко вълшебно за вас! + +### Създайте таблици за модели във вашата база данни + +Последната стъпка тук е да добавим нашия нов модел към базата данни. Първо трябва да накараме Django да разбере, че имаме някои промени в нашия модел. (Току-що го създадохме!) Отидете до прозореца на вашата конзола и напишете `python manage.py makemigrations blog`. Ще изглежда така: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Забележка:** Не забравяйте да запазите файловете, които редактирате. В противен случай компютърът ви ще изпълни предишната версия, която може да ви даде неочаквани съобщения за грешка. + +Django подготви миграционен файл за нас, който сега трябва да приложим към нашата база данни. Въведете `python manage.py migrate blog` и изходът трябва да бъде както следва: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Ура! Моделът ни на публикация вече е в нашата база данни! Би било хубаво да го видите, нали? Преминете към следващата глава, за да видите как изглежда вашата публикация! \ No newline at end of file diff --git a/bg-BG/django_orm/README.md b/bg-BG/django_orm/README.md new file mode 100644 index 00000000000..411c10c96a7 --- /dev/null +++ b/bg-BG/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM и QuerySets + +В тази глава ще научите как Django се свързва с базата данни и съхранява данни в нея. Нека се потопим! + +## Какво е QuerySet? + +QuerySet е по същество списък на обекти на даден Модел. QuerySets ви позволяват да четете данните от базата данни, да ги филтрирате и да ги подредите.. + +Най-лесно е да се учи чрез пример. Нека опитаме това, нали? + +## Django shell + +Отворете вашата локална конзола (не на PythonAnywhere) и въведете тази команда: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +Ефектът трябва да бъде такъв: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +Вече си в интерактивната конзола на Django. Това е точно като Python подкана, но с допълнителна магия на Django. :) Тук можеш да използваш всички Python команди. + +### Всички обекти + +Нека се опитаме първо да покажем всички наши публикации. Можете да направите това със следната команда: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Ами сега! Появи се грешка. Това ни казва, че няма Post. Правилно е - забравихме да го внесем първо! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +Импортираме модела `Post` от `blog.models`. Нека опитаме отново да покажем всички публикации: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +Това е списък на публикациите, които създадохме по-рано! Създадохме тези публикации чрез администраторския интерфейс на Django. Но сега искаме да създаваме нови публикации с помощта на Python, така че как да направим това? + +### Създаване на обект + +Ето как създавате нов обект Post в базата данни: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Но тук имаме една липсваща съставка: `me`. Трябва да предадем инстанция на модел `User` като автор. Как да направим това? + +Нека първо да импортираме модел User: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +Какви потребители имаме в нашата база данни? Опитайте това: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +Това е суперпотребителят, който създадохме по-рано! Нека сега вземем потребителя (коригирайте този ред, за да използвате вашето потребителско име): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +Както можете да видите, сега `get` a `User` с `username`, което се равнява на „ola“. Яко! + +Сега най-накрая можем да създадем нашия пост: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Ура! Искате ли да проверите дали работи? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +Ето, още една публикация в списъка! + +### Добавете още публикации + +Вече можете да се позабавлявате малко и да добавяте още публикации, за да видите как работи. Добавете още две или три и след това преминете към следващата част. + +### Филтрирайте обекти + +Голяма част от QuerySets е възможността да ги филтрирате. Да речем, че искаме да намерим всички публикации, на които потребителят ola е автор. Ще използваме `filter` вместо `all` в `Post.objects.all()`. В скобите посочваме на кое условие(я) трябва да отговаря блог публикацията, за да се озове в нашия набор от заявки. В нашия случай условието е `author/0> да бъде равен на me`. Начинът да го напишем в Django е `author=me`. Сега нашата част от кода изглежда така: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Или може би искаме да видим всички публикации, които съдържат думата 'title' в полето `title`? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Забележка** Има два знака за подчертаване (`_`) между `title` и `contains`. ORM на Django използва това правило за разделяне на имена на полета ("title") и операции или филтри ("contains"). Ако използвате само една долна черта, ще получите грешка като "FieldError: Не може да разреши ключовата дума title_contains". + +Можете също така да получите списък с всички публикувани публикации. Правим това, като филтрираме всички публикации, които имат `published_date` са зададени в миналото: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +За съжаление, публикацията, която добавихме от конзолата Python, все още не е публикувана. Но можем да променим това! Първо получете екземпляр от публикация, която искаме да публикуваме: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +И след това го публикувате с нашия метод `publish`: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Сега опитайте отново да получите списък с публикувани публикации (натиснете клавиша със стрелка нагоре три пъти и натиснете `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Подреждане на обекти + +QuerySets също ви позволяват да поръчате списъка с обекти. Нека се опитаме да ги поръчаме от полето `created_date`: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +Можем също да обърнем подреждането, като добавим `-` в началото: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Сложни заявки чрез свързване на методи + +Както видяхте, някои методи на `Post.objects` връщат QuerySet. Същите методи от своя страна могат също да бъдат извикани на QuerySet и след това ще върнат нов QuerySet. По този начин можете да комбинирате ефекта им, като ги **свържете** заедно: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +Това е наистина мощно и ви позволява да пишете доста сложни заявки. + +Готино! Вече сте готови за следващата част! За да затворите конзолата, въведете това: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/bg-BG/django_start_project/README.md b/bg-BG/django_start_project/README.md new file mode 100644 index 00000000000..da642fee45a --- /dev/null +++ b/bg-BG/django_start_project/README.md @@ -0,0 +1,260 @@ +# Вашият първи проект с Django! + +> Част от тази глава е базирана на ръководства от Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Части от тази глава са базирани на [django-marcador ръководство](http://django-marcador.keimlink.de/), лицензирано съгласно лиценза Creative Commons Attribution-ShareAlike 4.0 International. Ръководството на django-marcador е защитено с авторско право от Markus Zapke-Gründemann et al. + +Ще създадем малък блог! + +Първата стъпка е да започнете нов проект на Django. По принцип това означава, че ще изпълним някои скриптове, предоставени от Django, които ще създадат скелета на проект на Django за нас. Това е само куп директории и файлове, които ще използваме по-късно. + +Имената на някои файлове и директории са много важни за Django. Не трябва да преименувате файловете, които предстои да създадем. Преместването им на друго място също не е добра идея. Django трябва да поддържа определена структура, за да може да намери важни неща. + +> Не забравяйте да стартирате всичко във virtualenv (виртуалната среда). Ако не видите префикс `(myvenv)` в конзолата си, трябва да активирате своята virtualenv. Обяснихме как да направим това в главата **Инсталация на Django** в частта **Работа с virtualenv**. Въвеждането `myvenv\Scripts\activate`` в Windows или <0>source myvenv/bin/activate` в Mac OS X или Linux ще направи това вместо вас. + + + +Във вашата Mac OS X или Linux конзола трябва да изпълните следната команда. ** Не забравяйте да добавите точка `.` в края!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> Точката `.` е от решаващо значение, тъй като казва на скрипта да инсталира Django във вашата текуща директория (за която точката `.` е препратка). +> +> **Забележка** Когато пишете командата по-горе, не забравяйте, че въвеждате само частта, която започва от `django-admin`. Частта `(myvenv) ~/djangogirls$`, показана тук, е само пример за подкана, която ще покани твоето въвеждане във твоя команден ред. + + + + + +В Windows трябва да изпълните следната команда. **(Не забравяйте да добавите точка `.` в края)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> Точката `.` е от решаващо значение, тъй като казва на скрипта да инсталира Django във вашата текуща директория (за която точката `.` е препратка). +> +> **Забележка** Когато пишете командата по-горе, не забравяйте, че въвеждате само частта, която започва от `django-admin.exe`. Частта `(myvenv) C:\Users\Name\djangogirls>`, показана тук, е само пример за подкана, която ще покани твоето въвеждане във твоя команден ред. + + + +`django-admin.py` е скрипт, който ще създаде директории и файлове за вас. Сега трябва да имате структура на директория, която изглежда така: + + djangogirls + ├── manage.py + ├── mysite + │ ├── __init__.py + │ ├── settings.py + │ ├── urls.py + │ └── wsgi.py + ├── myvenv + │ └── ... + └── requirements.txt + + +> **Забележка**: в структурата на вашата директория ще видите и вашата `venv` директория, която създадохме преди. + +`manage.py` е скрипт, който помага при управлението на сайта. С него ще можем (освен всичко друго) да стартираме уеб сървър на нашия компютър, без да инсталираме нищо друго. + +Файлът `settings.py` съдържа конфигурацията на вашия уебсайт. + +Спомняте ли си, когато говорихме за пощенски превозвач, проверяващ къде да достави писмо? `urls.py` файлът съдържа списък от модели, използвани от `urlresolver`. + +За сега игнорираме останалите файлове, тъй като няма да ги променяме. Единственото нещо, което трябва да запомните, е да не ги изтриете случайно! + +## Промяна на настройките + +Нека направим някои промени в `mysite/settings.py`. Отворете файла с помощта на редактора на кода, който сте инсталирали по-рано. + +**Забележка**: Имайте предвид, че `settings.py` е обикновен файл, като всеки друг. Можете да го отворите от редактора на кода, като използвате "file -> open" от менюто. Това трябва да ви изведе обичайния прозорец, в който можете да се придвижите до вашия файл `settings.py` и да го изберете. Освен това можете да отворите файла, като отворите папката djangogirls на вашия работен плот и щракнете с десния бутон върху него. След това изберете редактора на кода от списъка. Изборът на редактора е важен, тъй като може да имате инсталирани други програми, които могат да отворят файла, но няма да ви позволят да го редактирате. + +Би било хубаво да имаме точното време на нашия уебсайт. Отидете в [списъка на часовите зони на Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) и копирайте съответната часова зона (ЧЗ) (напр. `Европа/Берлин`). + +В `settings.py` намерете реда, който съдържа `TIME_ZONE` и го модифицирайте, за да изберете своя собствена часова зона. Например: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +Езиков код се състои от езика, напр. `en` за английски или `de` за немски, и кодът на държавата, напр. `de` за Германия или `ch` за Швейцария. Ако английският не е вашият роден език, можете да добавите това, за да промените бутоните по подразбиране и известията от Django, за да бъдат на вашия език. Така че ще имате бутон „Отказ“, преведен на езика, който сте дефинирали тук. [Django идва с много подготвени преводи](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +Ако искате друг език, променете езиковия код, като промените следния ред: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +Ще трябва също да добавим път за статични файлове. (Ще разберем всичко за статичните файлове и CSS по-късно в ръководството.) Слезте до *края* на файла и точно под надписа `STATIC_URL` добавете нов, наречен `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +Когато `DEBUG` е `True` и `ALLOWED_HOSTS` е празен, хостът е валидиран срещу `['localhost', '127.0.0.1', '[::1]']`. Това няма да съвпада с името на хоста ни в PythonAnywhere, след като разширим нашето приложение, така че ще променим следната настройка: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Забележка**: Ако използвате Chromebook, добавете този ред в долната част на вашия settings.py файл:    `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Също така добавете `.amazonaws.com` към `ALLOWED_HOSTS`, ако използвате cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Създаване на база данни + +Има много различни софтуерни бази данни, които могат да съхраняват данни за вашия сайт. Ще използваме тази по подразбиране `sqlite3`. + +Това вече е настроено в тази част на вашия `mysite/settings.py` файл: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +За да създадем база данни за нашия блог, нека пуснем следното в конзолата: `python manage.py migrate` (трябва да бъдем в директорията `djangogirls`, която съдържа ` manage.py` файл). Ако това върви добре, трябва да видите нещо подобно: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... ОК + + +И ние сме готови! Време е да стартирате уеб сървъра и да видите дали уебсайтът ни работи! + +## Стартиране на уеб сървъра + +Трябва да сте в директорията, която съдържа файла `manage.py` (директорията `djangogirls`). В конзолата можем да стартираме уеб сървъра, като пуснем `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Ако сте на Chromebook, използвайте вместо това тази команда: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> Прегледахме как работят уеб сървърите в главата **Как работи Интернет**. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/bg-BG/django_templates/README.md b/bg-BG/django_templates/README.md new file mode 100644 index 00000000000..2faa3f72cbf --- /dev/null +++ b/bg-BG/django_templates/README.md @@ -0,0 +1,108 @@ +# Django шаблони + +Време е да покажем на екран малко данни! Django има вградени **template tags** за тази цел. + +## Какви са тези шаблонни етикети? + +Виждате, в HTML не може наистина да пишете Python код, защото търсачките не го разбират. Те знаят само HTML. Знаем, че HTML е статичен, докато Python е по-динамичен. + +**Django template tags** ни позволяват да прехвърлим Python нещата към HTML, така че да изграждаме динамични сайтове по-бързо. Супер! + +## Показване на шаблон за лист от публикации + +В предишната глава дадохме на нашия шаблон лист от публикации с променливата `posts`. Сега ще го покажем на екран с HTML. + +За да отпечатаме променливата в шаблоните на Django, използваме къдрави скоби с името на променливата вътре ето така: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Пробвайте това във вашия шаблон `blog/templates/blog/post_list.html`. Отворете го в редактора си и заместете всичко от вторият `
` до третият `
` с `{{ posts }}`. Запазете файла и опреснете страницата за да видите резултатите: + +![Фигура 13.1](images/step1.png) + +Както може да видите, всичко което имаме е това: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +Това означава, че Django го разбира като лист от обекти. Помните ли от **Въведение в Python** как показваме листове? Да, с for цикли! При Django шаблоните ги правим така: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Пробвайте това във вашия шаблон. + +![Фигура 13.2](images/step2.png) + +Работи! Но ние искаме публикациите ни да се показват като статичните публикации, които създадохме по-рано в главата **Въведение в HTML**. Можете да смесвате HTML с шаблони. Нашето `body` ще изглежда така: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Всичко, което сложите между `{% for %}` и `{% endfor %}` ще се повтаря за всеки обект в листа. Опреснете страницата си: {% endraw %} + +![Фигура 13.3](images/step3.png) + +Забелязахте ли, че този път използвахме малко по-различно означение (`{{ post.title }}` или `{{ post.text }}`)? Достъпваме данните във всяко едно поле дефинирано в нашия `Post` модел. Също така `|linebreaksbr` изпраща текста на публикациите през филтър и превръща в абзаци. + +## Още едно нещо + +Ще е хубаво да видим дали уеб страницата ви работи в Internet, нали? Нека го прехвърлим отново на PythonAnywhere. Ето преглед на стъпките: + +* Първо, изпратете кода си към GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* След това влезте пак в [PythonAnywhere](https://www.pythonanywhere.com/consoles/) акаунта си и отидете на **Bash console** (или стартирайте нова) и напишете командите: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Не забравяйте да заместите `` с вашия актуален PythonAnywhere субдомейн, без скобите.) + +* Накрая отидете на ["Web" страница](https://www.pythonanywhere.com/web_app_setup/) и натиснете **Reload** на вашата апликация. (За да достигнете други PythonAnywhere страници от конзолата, използвайте бутона от менюто в горния десен ъгъл.) Вашете обновление трябва да съществува на https://subdomain.pythonanywhere.com -- проверете в търсачката си! Ако публикациите на вашата PythonAnywhere страница не съвпадат с тези, които се появяват на локалния ви сървър, това е нормално. Базата от данни на локалния ви компютър не са синхронизирани с останалите ви файлове на PythonAnywhere. + +Поздравления! Сега добавете нова публикация в администрацията на Django (помнете да добавите published_date!) Бъдете сигурни, че сте администрацията на Django на своята страница в pythonanywhere, https://subdomain.pythonanywhere.com/admin. След това презаредете страницата за да видите дали публикациите са налице. + +Работи безупречно? Горди сме с теб! Сега отстъпи от компютъра си за малко – заслужи си почивка. :) + +![Фигура 13.4](images/donut.png) \ No newline at end of file diff --git a/bg-BG/django_urls/README.md b/bg-BG/django_urls/README.md new file mode 100644 index 00000000000..be16809c102 --- /dev/null +++ b/bg-BG/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +Готови сме да създадем нашата първа уеб страница: начална страница на твоя блог! Но първо нека научим малко повече за Django URLs. + +## Какво е URL? + +URL е уеб адрес. Може да видиш URL всеки път когато посещаваш уебсайт – видимо е в полето за адрес на твоята търсачка. (Да! `127.0.0.1:8000` е URL! И `https://djangogirls.org` също е URL.) + +![URL](images/url.png) + +Всяка страница в Internet има нужда от собствен URL. По този начин твоето приложение знае какво трябва да покаже на потребителя, който отваря този URL. В Django използваме нещо наречено `URLconf` (URL конфигурация). URLconf е пакет от примери, които Django се опитва да съпостави със запитания URL за да намери правилния изглед. + +## Как работят URL в Django? + +Нека отворим файла `mysite/urls.py` в редактора си и видим как изглежда: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +Както може да видите, Django вече е сложил нещо за нас тук. + +Редовете между трите кавички (`'''` or `"""`) се наричат docstrings – може да ги изписвате в началото на файла, класове или методи за да обясните какво прави кода - като коментар. Те няма да се изпълнят от Python. + +Администртивния URL, който посетихте в предната глава е вече тук: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +Този ред означава, че за всеки URL, който започва с `admin/`, Django ще намери съответстващ изглед *view*. В този случай въвеждаме много администраторски URL, така че да не е претъпкано в този малък файл – по-четимо и по-чисто. + +## Твоя първи Django URL! + +Време е да създадете вашия първи URL! Искаме 'http://127.0.0.1:8000/' да бъде началната страница на нашия блог и да показва лист от публикации. + +Също така искаме да задържим файла `mysite/urls.py` чист, така че да въведем URL от нашата `blog` апликация към главният файл `mysite/urls.py`. + +Давайте напред, като добавите ред с който ще въведете `blog.urls`. Също ще искате да направите промени в `from django.urls…` реда, защото използваме функция `include`, така че вие трябва да добавите `import` към този ред. + +Вашият файл `mysite/urls.py` трябва да изглежда ето така: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django сега ще пренасочва всичко, което идва към 'http://127.0.0.1:8000/' до `blog.urls` и търси за следващи инструкции тук. + +## blog.urls + +Създайте нов файл с име `urls.py` в директория на `blog` и го отворете с редактора си. И така! Добавете следните два реда: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Тук въвеждаме функцията на Django `path` и всички наши изгледи ( `views`) от `blog` апликацията. (Все още нямаме никакви, но ще стигнем до там след минута!) + +След това можем да добавим наши първи URL образец: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +Както виждате, сега приписваме изгледа наречен `post_list` към началния (root) URL. Този URL образец ще съвпадне с празен низ и преобразувателя в Django URL ще игнорира домейн името (т.е.,http://127.0.0.1:8000/), което започва с пълния път на URL. Този образец казва на Django, че `views.post_list` е правилното място да отиде, ако някой влезе в сайта ви на адрес 'http://127.0.0.1:8000/'. + +Последната част, `name='post_list' + +

Ако сега се опитате да посетите http://127.0.0.1:8000/, ще видите съобщение от рода на 'web page not available' . Това е така, защото сървърът (помните командата runserver`?) вече не е активен. Погледнете в конзолата на сървъра си и разберете защо. + +![Error (Грешка)](images/error1.png) + +Конзолата ви показва грешка, но не се тревожете – това всъщност е много полезно: Казва ви, **че няма атрибут с име 'post_list'**. Това е името на изгледа, който Django се опитва да намери и използва, но ние не сме го създали все още. На този етап, вашият `/admin/` също няма да работи. Не се тревожете – ще стигнем и до там. Ако виждате съобщение с друга греша, опитайте се да презаредите уеб сървъра. За да направите това, в конзолния прозорец, където сте пуснали сървъра, натиснете Ctrl+C за да го спрете (Ctrl + C заедно). На Windows може би трябва да натиснете Ctrl+Break. След това трябва да презаредите уеб сървъра като напишете командата `python manage.py runserver`. + +> Ако искате да научите повече за Django URLconfs, вижте в официалната документация: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/bg-BG/django_views/README.md b/bg-BG/django_views/README.md new file mode 100644 index 00000000000..02efa058ccc --- /dev/null +++ b/bg-BG/django_views/README.md @@ -0,0 +1,44 @@ +# Django views - време за създаване! + +Време е да премахнем пречката, която създадохме в последната глава! :) + +*view* е мястото, където поставяме "логиката" на приложението ни. Ще изиска информация от моделът, който създадохме по-рано и ще го подаде на шаблона. Ще създадем шаблон в следващата глава. Изгледите са просто Python фукнции, които са малко по-сложни от тези, които написахме в главата **Въведение в Python**. + +Изгледите са във файла `views.py`. Ние ще добавим първи си изглед към файла `blog/views.py`. + +## blog/views.py + +И така, нека отворим файла в редактора си видим какво има в него: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Няма почти нищо все още. + +Помнете, че редовете, които започват с `#` са коментари – което означава, че тези редове няма да се четат от Python. + +Нека създадем *view* както коментара предлага да направим. Добавете следният минимален изглед под него: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Както забелязвате, създаваме фукнция (`def`) наречена `post_list`, която взима за стойност `request` ще върне друга функция `render`, взимайки стойността, шаблона и контекста. + +Запазете файла и отидете на http://127.0.0.1:8000/ за да видите какво имаме там. + +Друга грешка! Прочетете какво се случва сега: + +![Error (Грешка)](images/error.png) + +Това показва, че сървърът отново работи, но все още не изглежда както трябва, нали? Не се тревожете. Това е само страница с грешка, няма от какво да се страхувате! Също като съобщение с грешка в конзолата, тези са всъщност от голяма полза. Можете да прочетете, че *TemplateDoesNotExist*. Нека отстраним тази грешка и създадем шаблон в следващата глава! + +> Научете повече за Django изгледите като прочетете официалната документация: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/bg-BG/dynamic_data_in_templates/README.md b/bg-BG/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..bd03e45ec39 --- /dev/null +++ b/bg-BG/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Динамични данни в шаблоните + +Имаме различни парчета на места: `Post` моделът е дефиниран в `models.py`, имаме `post_list` във `views.py` и добавен шаблон. Но как всъщност ще направим, така че нашите публикации да се показват на HMTL шаблон? Защото това е, което искаме да направим – да вземем някакво съдържание (запазените модели в базата от данни) и да се показват хубаво на нашия шаблон, нали? + +Това е точно, което *views* трябва да правят: свързват моделите с шаблоните. В нашия изглед за `post_list` ще трябва да вземем моделите, които искаме да показваме и да ги предадем на шаблоните. В изгледа ние определяме какво (модел) ще се изобразява в шаблона. + +Добре, как ще го постигнем? + +Трябва да отворим `blog/views.py` в редактора си. До момента `post_list` изгледа е такъв: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Помните ли когато говорихме за вмъкване на код написан в различни файлове? Сега е моментът, в който трябва да вмъкнем модела, който създадохме в `models.py`. Ще добавим реда `from .models import Post` така: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +Точката преди `models` означава настояща директория или настояща апликация. Двата файла `views.py` и `models.py` са в една и съща директория. Това означава, че можем да използваме `.` и името на файла (без разширението `.py`). Тогава въвеждаме името на модела (`Post`). + +Но след това какво? За да вземем всъщност публикация от `Post` модела ни трябва нещо наречено `QuerySet`. + +## QuerySet + +Вече трябва да сте запознати как работят QuerySets. Говорихме за тях в главата [Django ORM (QuerySets)](../django_orm/README.md). + +Сега искаме публикуваните ни блог постове сортирани по дата на публикуване, нали? Вече направихме това в главата QuerySets! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +И така, нека да отворим файла `blog/views.py` в редактора и добавим този код към функцията `def post_list(request)` -- но нека не забравяме първо да добавим `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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 в списъка с публикации на нашия блог, ни остават две неща: + +1. Натиснете `posts` QuerySet в контекста на шаблона, като промените функцията `render`. Ще направим това сега. +2. Променете шаблона да показва `posts` QuerySet. Ще разгледаме това в следващата глава. + +Моля забележете, че създадохме променлива за нашия QuerySet: `posts`. Ползвайте това като име на нашия QuerySet. От сега нататък можем да се отнасяме към него с това име. + +В `render` функцията имаме един параметър `request` (всичко се получава от потребителят чрез Internet) и друг даващ файла на шаблона (`'blog/post_list.html'`). Последният параметър, `{}`, е място в което може да добавим някакви неща, така че шаблона да ги използва. Трябва да им дадем имена (ще се придържаме към `'posts'` засега). :) Трябва да изглежда ето така: `{'posts': posts}`. Забележете, че частта преди `:` е низ; трябва да го заградите с кавички: `''`. + +И така накрая нашия файл `blog/views.py` трябва да изглежда така: + +{% filename %}blog/views.py{% endfilename %} + +```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/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/bg-BG/extend_your_application/README.md b/bg-BG/extend_your_application/README.md new file mode 100644 index 00000000000..1017da252ae --- /dev/null +++ b/bg-BG/extend_your_application/README.md @@ -0,0 +1,215 @@ +{% set warning_icon = '' %} + +# Продължете апликацията си + +Вече завършихме всички различни стъпки необходими за създаването на нашия уеб сайт: знаем как да напишем модел, URL, изглед и шаблон. Знаем също и как да направим сайта ни хубав. + +Време е за практика! + +Първото нешо, което ни е необходимо за блога е очевидно страница, която да показва една публикация, нали така? + +Вече разполагаме с `Post` модел, така че няма нужда да правим промени в `models.py`. + +## Създайте връзка към шаблона със съдържанието на поста. + +Ще започнем като добавим връзка във файла `blog/templates/blog/post_list.html`. Отворете го в редактора си, като до момента трябва да изглежда по този начин: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +

+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %} Искаме да имаме връзка от заглавието на поста в листа с публикациите до страницата със съдържанието на поста. Нека променим `

{{ post.title }}

`, така че да се свързва със съдържанието на страницата:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %} Време е да обясним мистериозния код `{% url 'post_detail' pk=post.pk %}`. Може би забелязахте, че означението `{% %}` означава, че използваме Django шаблонни етикети. Този път ще изполваме такъв, който създава URL за нас! {% endraw %} + +`post_detail` частта означава, че Django трябва да очаква URL в `blog/urls.py` с име name=post_detail + +А какво за `pk=post.pk`? `pk` идва накратко от primary key, което е уникален идентификатор за всеки един запис в базата данни. Всеки Django модел има поле, което служи за негов първоначален код (primary key), и каквото и друго име да има, то може също да се съотнесе като "pk". Тъй като не уточнихме първоначалната стойност в нашия `Post` модел, Django създава един за нас (по подразбиране, полето "id" , съдържащо номер, който се увеличава при всеки запис, т.е. 1, 2, 3) и го добавя към полето на всеки от нашите постове. Можем да достигнем primary key като напишем `post.pk`, по същия начин достъпваме други полета (`title`, `author`, и т.н.) в нашия `Post` обект! + +Сега като отидем на http://127.0.0.1:8000/ ще видим грешка ( както се очаквкаше, тъй като все още нямаме URL или *view* за `post_detail`). Ще изглежда така: + +![NoReverseMatch грешка](images/no_reverse_match2.png) + +## Създаване на URL към съдържанието на поста + +Нека създадем URL в `urls.py` за нашия `post_detail` *view*! + +Искаме първия ни пост да бъде показван на този **URL**: http://127.0.0.1:8000/post/1/ + +Сега да направим URL във файла `blog/urls.py`, който да насочва Django към *view* наречен `post_detail`, който ще показва целия блог пост. Отворете файла `blog/urls.py` в редактора си и добавете следния ред `path('post//', views.post_detail, name='post_detail'),`, така че файлът да изглежда по този начин: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +Тази част `post//` уточнява URL образеца -- ще ви го обясним: + +- `post/` означава, че URL трябва да започва с думата **post** последвана от **/**. Дотук добре. +- `` -- тази част е по-сложна. Означава, че Django очаква стойност цяло число и ще го преведе към изгледа (view) като променлива наречена `pk`. +- `/` – след това ни е необходима **/** преди да завършим URL. + +Това означава, че когато напишем в търсачката си `http://127.0.0.1:8000/post/5/`, Django ще разбере, че търсите за *view* наречен `post_detail` и изпраща информацията, че този `pk` съответства на `5` спрямо този *view* (изглед). + +И така, добавихме нов URL образец към `blog/urls.py`! Нека презаредим страницата: http://127.0.0.1:8000/ Бум! Сървърът отново спря да работи. Погледнете в конзолата -- както се очакваше, има нова грешка! + +![AttributeError](images/attribute_error2.png) + +Помните ли каква е следващата стъпка? Добавяне на нов изглед (view)! + +## Добавяне на изглед за съдържанието на поста + +Този път на нашето *view* даваме допълнителен параметър, `pk`. Нашето *view* трябва да го прихване, нали? Така, ще дефинираме нашата функция като `def post_detail(request, pk):`. Забележете, че този параметър трябва да има точно същото име като на `urls` (`pk`), който уточнихме по-рано. Също така забележете, че пропускането на тази променлива е неправилно и в резултат ще доведе до грешка! + +Сега, искаме да вземем само и единствено една публикация. За да направим това, можем да използваме querysets ето така: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +Но този код има проблем. Ако нямаме `Post` с даден `primary key` (`pk`) ще имаме много грозна грешка! + +![DoesNotExist грешка](images/does_not_exist2.png) + +Ние не искаме това! За щастие Django идва с нещо, с което да се справи вместо нас: `get_object_or_404`. В случай, че няма `Post` със зададен `pk`, ще се покаже на екрана много по-добре, `Page Not Found 404` страница. + +![Page not found](images/404_2.png) + +Хубавото е, че всъщност и вие можете да си създадете такава страница `Page not found` и да я направите колкото си искате хубава. Но не е чак толкова важно в момента, затова ще го пропуснем. + +ОК, време е да добавим *view* към нашия файл `views.py`! + +В 0>blog/urls.py
създадохме URL правило наречено `post_detail`, което се отнася до изглед с име `views.post_detail`. Това означава, че Django ще очаква изглед функция наречена `post_detail` вътре в `blog/views.py`. + +Трябва да отворим `blog/views.py` в редактора и да добавим следния код близо до другите редове `from` : + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 + +``` + +И накрая на файла ще добавим нашия изглед (*view*): + +{% filename %}blog/views.py{% endfilename %} + +```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 (Изглед с лист от постове)](images/post_list2.png) + +Работи! Но сега какво става, когато кликнете върху връзката със заглавието на поста? + +![TemplateDoesNotExist грешка](images/template_does_not_exist2.png) + +Оо, не! Друга грешка! Но вече знаем как да се справим с това, нали? Трябва да добавим нов шаблон! + +## Създайте шаблон за съдържанието на поста + +Ще създадем файл в `blog/templates/blog` наречен `post_detail.html`, и ще го отворим в редактора. + +Впишете следния код: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +Още веднъж удължаваме `base.html`. В блока `content` искаме да покажем датата на публикуване на поста (ако същестрвува), заглавието и текста. Но трябва да обсъдим други важни работи, нали? + +{% raw %}`{% if ... %} ... {% endif %}` е шаблонен етикет, който използваме, когато искаме да проверим нещо. (Помните ли `if ... else ...` от главата ** Въведение в Python**?) В този случай искаме да проверим дали `published_date` (датата на публикване) на поста не е празна.{% endraw %} + +ОК, можем да отворим страницата ни наново и ще видим, че `TemplateDoesNotExist` сега го няма. + +![Post detail page (Страница със съдържанието на поста)](images/post_detail2.png) + +Ихаа! Работи! + +# Време за прехвърляне на файловете! + +Би било добре да видите дали сайта ви работи на PythonAnywhere нали? Нека опитаме да прехвърлим всичко отново. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push + + +Тогава, в [PythonAnywhere Bash конзолата](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Не забравяйте да замените `` с вашият актуален PythonAnywhere субдомейн, без скобите.) + +## Обновяване на статичните файлове на сървърът: + +Сървъри като PythonAnywhere обичат да се отнасят към "статичните файлове" (като CSS файлове) различно от Python файловете, защото те могат да оптимизират зареждането им по-бързо. В резултат, когато правим промени на нашите CSS файлове трябва да напишем допълнителни команди на сървъра за да му кажем да ги обнови. Командата се казва `collectstatic`. + +Започнете като активирате виртуалната си среда, ако не е активна от преди това (PythonAnywhere използва команда наречена `workon` да направи това, същото е както когато използваме команда `source myenv/bin/activate` на своя компютър. + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +Командата `manage.py collectstatic` е нещо като `manage.py migrate`. Правим промени на кода си, след това казваме на Django да приложи тези промени или към събраните статизни файлове на сървъра или към базата данни. + +Във всеки случай сега сме готови да отидем на ["Web" страницата](https://www.pythonanywhere.com/web_app_setup/) (от бутона на менюто в горния десен ъгъл) и натиснем **Reload**, след това погледнете страницата https://subdomain.pythonanywhere.com за да видите резултата. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/bg-BG/how_the_internet_works/README.md b/bg-BG/how_the_internet_works/README.md new file mode 100644 index 00000000000..580b879e95f --- /dev/null +++ b/bg-BG/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# Как работи интернет + +> За читателите у дома: тази глава е разгледана във видеото [Как работи интернет](https://www.youtube.com/watch?v=oM9yAA09wdc). +> +> Тази глава е вдъхновена от беседата "Как работи Интернет" от Джесика Маккелар (http://web.mit.edu/jesstess/www/). + +Обзалагаме се, че използвате интернет всеки ден. Но всъщност знаете ли какво се случва, когато въведете адрес като https://djangogirls.org в браузъра си и натиснете `enter`? + +Първото нещо, което трябва да разберете е, че уебсайтът се състои от куп файлове, записани на твърд диск - точно като вашите филми, музика или снимки. Има обаче една част, която е уникална за уебсайтовете: те включват компютърен код, наречен HTML. + +Ако не сте запознати с програмирането, в началото може да е трудно да разберете HTML, но вашите уеб браузъри (като Chrome, Safari, Firefox и др.) го харесват. Уеб браузърите са създадени да разбират този код, да следват неговите инструкции и да представят тези файлове, от които е направен уебсайтът ви, точно по начина, по който искате. + +Както при всеки файл, ние трябва да съхраняваме HTML файлове някъде на твърд диск. За интернет използваме специални, мощни компютри, наречени *сървъри*. Те нямат екран, мишка или клавиатура, защото основната им цел е да съхраняват данни и да ги предоставят. Ето защо те се наричат *сървъри* - защото те *предоставят* вашите данни. + +Добре, но искате да знаете как изглежда интернет, нали? + +Нарисувахме ви снимка! Изглежда така: + +![Фигура 1.1](images/internet_1.png) + +Прилича на каша, нали? Всъщност това е мрежа от свързани машини (гореспоменатите *сървъри*). Стотици хиляди машини! Много, много километри кабели по света! Можете да посетите уебсайта на Submarine Cable Map (http://submarinecablemap.com), за да видите колко сложна е мрежата. Ето екранна снимка от уебсайта: + +![Фигура 1.2](images/internet_3.png) + +Очарователно е, нали? Но не е възможно да има жица между всяка машина, свързана към Интернет. И така, за да достигнем машина (например тази, на която е записан https://djangogirls.org), трябва да предадем заявка през много, много различни машини. + +Изглежда така: + +![Фигура 1.3](images/internet_2.png) + +Представете си, че когато въвеждате https://djangogirls.org, изпращате писмо, което гласи: "Скъпи момичета на Django, искам да видя уебсайта djangogirls.org. Изпратете ми го, моля!" + +Вашето писмо отива до най-близката до вас поща. След това преминава към друга, която е малко по-близо до вашия адресат, след това към друга и друга, докато не бъде доставено до местоназначението си. Единственото уникално нещо е, че ако изпратите много писма (*пакети данни*) на едно и също място, те могат да преминат през напълно различни пощенски станции (*рутери*). Това зависи от начина, по който се разпределят във всеки офис. + +![Фигура 1.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/bg-BG/html/README.md b/bg-BG/html/README.md new file mode 100644 index 00000000000..f32488d74fa --- /dev/null +++ b/bg-BG/html/README.md @@ -0,0 +1,227 @@ +# Въвeдение в HTML + +Може би се питате какво е шаблон (template)? + +Шаблонът е файл който, можем да използваме неколкократно за да представим различна информация в последователен формат -- например, можете да използвате шаблон, който да ви помага да напишете писмо, защото макар че всяко писмо да може да съдържа различно съобщение и да бъде адресирано до различен човек, те ще споделят същия формат. + +Django формат шаблона е описан в език наречен HTML (Това е HTML, който споменахме в главата **Как работи Internet**). + +## Какво е HTML? + +HTML е код, който се интерпретира от търсачките -- като Chrome, Firefox, Safari -- за да покаже на екран страницата на потребителя. + +HTML идва от "HyperText Markup Language". **HyperText** означава, че е тип от текст който подпомага хипервръзки между страници. **Markup** означава, че сме взели документа и сме го означили с код за да кажем нещо (в този случай, търсачка) как да подразбира страницата. HTML кода е изграден от **tags** (етикети), всеки от които стартира с `<` и завършва с `>`. Тези етикети представляват маркирани елементи (**elements**). + +## Първият ви шаблон! + +Създаване на шаблон означава създаване на шаблонен файл. Всичко е файл, нали? Може би вече забелязахте това. + +Шаблоните се запазват в директория `blog/templates/blog`. Така че, първо създайте директория наречена `templates` в директорията на блога ви. След това създайте друга директория наречена `blog` вътре при вашите шаблони: + + blog + └───templates + └───blog + + +(Може би се чудите защо са ни нужни две директории наречени `blog` -- както ще откриете по-късно, това е много лесно установена практика, която прави живота ни по-лесен, когато нещата започват да стават по-сложни.) + +И сега създайте файл `post_list.html` (оставете го празен засега) в директорията `blog/templates/blog`. + +Вижте как изглежда сайта ви: http://127.0.0.1:8000/ + +> Ако все още имате грешка `TemplateDoesNotExist`, опитайте се да заредите сървъра си отново. Отидете в командния си ред, спрете сървъра като натиснете едновременно Ctrl+C (Клавишите Control и C заедно) и го стартирайте отново като напишете команда `python manage.py runserver` . + +![Фигура 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Отворете новият файл в редактора и добавете следното: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +Така, как изглежда уебсайта ви в момента? Отидете на: http://127.0.0.1:8000/ за да разберете + +![Фигура 11.2](images/step3.png) + +It worked. Nice work there! :) + +* The line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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) + +Всяка HTML страница е разделена на два елемена: **head** и **body**. + +* **head** е елемент, който съдържа информация относно документа, който е показан на екрана. + +* **body** е елемент, който съдържа всичко, което е показано като част от уеб страницата. + +Използваме `` за да кажем на търсачката за конфигурацията на страницата и `` какво точно е на страницата. + +Например, може да сложите заглавие на елемента вътре в `` ето така: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Запазете файла и презаредете страницата. + +![Фигура 11.3](images/step4.png) + +Забелязахте ли как търсачката ви разбра, че заглавието на блога е "Ola's blog"? Тълкува `Ola's blog` и показва текст с името на заглавието в лентата на търсачката (също така ще се използва за отметка (bookmarks) и т.н.). + +Вероятно забелязахте и, че отварящия етикет съвпада със затварящия с `/`, като тези елементи са вложени (например не можете да затворите определен етикет, докато не затворите всички, които са преди него). + +Също като да слагаме неща в кутии. Имате една голяма кутия, ``; в нея е `` и това съдържа други по-малки кутии: `

`. + +Трябва да следвате тези правила със затварящите етикети и вложените елементи - ако ли не, търсачката ви може и да не ги представи както трябва и страницата ви ще изглежда неправилно. + +## Персонализиране на шаблон + +Може малко да се позабавлявате и да опитате да направите свой шаблон! Ето няколко полезни етикета за целта: + +* `

Заглавие

` за най-важното ви заглавие +* `

Подзаглавие

` за заглавие от следващо ниво +* `

Под-подзаглавие

` …и т.н. до `
` +* `

Абзац

` +* `текст` набляга на текста +* `текст` удебелява текста +* `
` отива на нов ред (не може да сложите нищо в br, както и няма затварящ етикет ) +* `връзка` създава връзка +* `
  • първи елемент
  • втори елемент
` прави лист, точно като този! +* `
` дефинира секция от страницата +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Ето пример на пълен шаблон, копирайте и пренесете в `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +Дава ни този ефект: + +![Фигура 11.4](images/step6.png) + +Ихаа! Но дотук, нашият шаблон показва точно **същата информация** -- там където говорихме по-рано за шаблоните, които ни позволяват да показваме **различна** информация в **същия формат**. + +Това, което искаме е да показва истински публикации добавени в администратора на Django -- и там е където отиваме след това. + +## Още нещо: прехвърляне на файловете (deploy)! + +Би било добре да видим всичко това на живо в Internet, нали? Нека направим още едно прехвърляне на файлове към PythonAnywhere: + +### Запазете, and избутайте кода си към GitHub + +Първо, нека видим кои файлове се промениха след последното прехвърляне (напишете следните команди на локалния компютър, не на PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Бъдете сигурни, че сте в директорията на `djangogirls` и нека кажем на git да включи всички промени в тази директория: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +Преди да качим всички файлове, нека проверим какво ще качи `git` (всички файлове, които `git` ще качи ще се появят в зелено): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Почти сме там, сега е време да кажем да запази тези промени в хронологията си. Ще дадем съобщение за запазване ("commit message"), където описваме накратко какво сме променили. Може да напишете каквото си поискате на този етап, но е важно да се знае, че би трябвало да е нещо описващо от това, което сте направили, така че да се знае в бъдеще. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "Changed the HTML for the site." + + +> **Note** Make sure you use double quotes around the commit message. + +След като сме направили това, качваме (push) нашите промени на GitHub: + +{% filename %}command-line{% endfilename %} + + $ git push + + +### Издърпайте новия код на PythonAnywhere и презаредете страницата + +* Отворете [PythonAnywhere страницата](https://www.pythonanywhere.com/consoles/) и отидете на **Bash конзолата** (или стартирайте нова). След това напишете команда: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +Трябва да заместите `` с актуалния си PythonAnywhere субдомейн без скобите. Вашият субдомейн е потребителско ви име в PythonAnywhere, но в някои случай може да е различно (като например ако потребителското ви име съдържа главни букви). Така че, ако тази команда не работи, използвайте команда `ls` (показване на лист от файлове) за да намерите вашия субдомейн/име на папката, и след това да отидете в нея `cd`. + +Сега гледайте как се сваля кода ви. Ако искате да проверите дали е пристигнал, отидете на **"Files" страница** и вижте кода си на PythonAnywhere (може да достигнете други страници на PythonAnywhere от бутона на менюто в страницата на конзолата). + +* Накрая, отидете на ["Web" страницата](https://www.pythonanywhere.com/web_app_setup/) и натиснете **Reload** на вашата апликация. + +Обновлението трябва да е на живо! Отидете и презаредете страницата си в търсачката. Промените трябва да са видими. :) \ No newline at end of file diff --git a/bg-BG/installation/README.md b/bg-BG/installation/README.md new file mode 100644 index 00000000000..588df0983d6 --- /dev/null +++ b/bg-BG/installation/README.md @@ -0,0 +1,68 @@ +# Ако правите ръководството у дома + +Ако правите ръководството у дома, а не на някое от събитията на [Django Girls](https://djangogirls.org/events/), можете напълно да пропуснете тази глава сега и да отидете направо към главата [Как работи Интернет](../how_the_internet_works/README.md). + +Това е така, защото покриваме инсталирането на неща, каквито са необходими в ръководството - това е само допълнителна страница, която събира всички инструкции за инсталиране на едно място (което е полезно за някои формати на работилницата). Можете да изберете да инсталирате всичко, което е на тази страница в момента, ако желаете. Но ако искате да започнете да научавате неща, преди да инсталирате куп неща на вашия компютър, пропуснете тази глава и ние ще ви обясним по-късно инсталационните части, тъй като те са необходими. + +Късмет! + +# Ако посещавате уъркшоп + +Ако присъствате на някое от събитията на [Django Girls](https://djangogirls.org/events/): + +* Вашата работилница може да има "парти за инсталиране" преди основната работилница. Ако сте на парти за инсталиране, тази страница е за вас! Следвайте инструкциите тук, за да получите всичко необходимо за работния процес, с помощта на менторите, ако е необходимо. След това в основната работилница ще можете да пропуснете инструкциите за инсталиране, които ще срещнете в главното ръководство, когато стигнете до тях. +* Организаторите на вашата работилница може би са ви помолили да опитате у дома, за да инсталирате всичко на вашия компютър, преди да започне уъркшопът. Ако сте били помолени да направите това, тази страница е за вас! Следвайте инструкциите тук, както можете най-добре. След това в основната работилница, когато стигнете до стъпка за инсталиране в основното ръководство, ако не сте успели да инсталирате тази част, можете да получите помощ от вашия ментор. +* Ако вашият уъркшоп няма парти за инсталиране (или не можете да присъствате) и ако организаторите не са ви помолили да опитате да инсталирате всичко преди да сте пристигнали, пропуснете тази страница и отидете направо към главата [Как работи Интернет](../how_the_internet_works/README.md). Ще инсталирате всичко необходимо, докато работите през ръководството. + +# Инсталиране + +В това ръководство ще изграждате блог. За да направите това, докато преминавате през ръководството, ще бъдете инструктирани как да инсталирате различен софтуер на вашия компютър и да настроите някои онлайн акаунти, тъй като са необходими. Тази страница събира на едно място всички инструкции за инсталиране и регистрация (което е полезно за някои формати на работилницата). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Кратко въведение в командния ред {#command-line} + +Много от стъпките по-долу се споменават "конзолата", "терминала", "командния прозорец" или "командния ред" - всичко това означава едно и също нещо: прозорец на вашия компютър, в който можете да въведете команди. Когато стигнете до главното ръководство, ще научите повече за командния ред. Засега основното, което трябва да знаете, е как да отворите командния прозорец и как изглежда: {% include "/intro_to_command_line/open_instructions.md" %} + +# Инсталиране на Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Инсталиране на редактор на код {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Настройте virtualenv и инсталирайте Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Инсталиране на Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Отидете на [GitHub.com](https://www.github.com) и се регистрирайте за нов безплатен потребителски акаунт. Не забравяйте да запомните паролата си (добавете я към вашия мениджър на пароли, ако използвате такъв). + +# Create a PythonAnywhere account {#pythonanywhere-account} + +{% 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), защото вече сте обхванали материала в по-ранните глави. \ No newline at end of file diff --git a/bg-BG/intro_to_command_line/README.md b/bg-BG/intro_to_command_line/README.md new file mode 100644 index 00000000000..fa7f4f13ce2 --- /dev/null +++ b/bg-BG/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Въведение в интерфейса на командния ред + +> За читателите у дома: тази глава е разгледана във видеото [Вашият нов приятел: Командният ред](https://www.youtube.com/watch?v=jvZLWhkzX-8). + +Вълнуващо е, нали ?! Ще напишете първия си ред код само за няколко минути! :) + +**Нека ви запознаем с първия ви нов приятел: командният ред!** + +Следващите стъпки ще ти покажат как да използваш черния прозорец, който използват всички хакери. В началото може да изглежда малко страшно, но всъщност тази подкана просто чака команди от теб. + +> **Забележка** Моля, имайте предвид, че в тази книга използваме взаимозаменяемите термини „директория“ и „папка“, но те са едно и също нещо. + +## Какво е командният ред? + +Прозорецът, който обикновено се нарича **команден ред** или **интерфейсът на командния ред**, е текстово приложение за преглед, обработка и манипулиране на файлове на вашия компютър. Прилича много на Windows Explorer или Finder на Mac, но без графичния интерфейс. Други имена на командния ред са: *cmd*, *CLI*, *подкана*, *конзола* или *терминал*. + +## Отворете интерфейса на командния ред + +За да започнем някои експерименти, първо трябва да отворим интерфейса на командния ред. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## Подкана + +Сега трябва да видите бял или черен прозорец, който чака вашите команди. + + + +Ако сте на Mac или Linux, вероятно виждате `$`, ето така: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +На Windows, вероятно виждате `>`, ето така: + +{% filename %}command-line{% endfilename %} + + > + + +Погледнете раздела за Linux малко по-горе - ще видите нещо подобно, когато стигнете до PythonAnywhere по-късно в урока. + + + +Всяка команда ще бъде предварително обозначена с `$` или `>` и един интервал, но не бива да го въвеждате. Вашият компютър ще го направи вместо вас. :) + +> Само малка забележка: във твоя случай може да има нещо като `C:\Users\ola>` или `Olas-MacBook-Air:~ ola$` преди знака на подкана и това е 100% ОК. + +Частта до и включително `$` или `>` се нарича *командния ред* или *подкана* за кратко. То те подканва да въведеш нещо там. + +В ръковдството, когато искаме да въведете команда, ще включим `$` или `>`, а понякога и повече вляво. Игнорирай лявата част и въведи само командата, която започва след подканата. + +## Вашата първа команда (УРА!) + +Нека започнем с въвеждането на тази команда: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +И след това натиснете `enter`. Това е нашият резултат: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +Както можете да видите, компютърът току-що отпечата вашето потребителско име. Яко, а? :) + +> Опитайте да въведете всяка команда; не копирайте-поставете. Ще запомните повече по този начин! + +## Основи + +Всяка операционна система има малко по-различен набор от команди за командния ред, така че не забравяйте да следвате инструкциите за вашата операционна система. Нека опитаме това, става ли? + +### Текуща директория + +Би било хубаво да знаем къде сме сега, нали? Да видим. Въведете тази команда и натиснете `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Забележка: 'pwd' означава 'print working directory' (принтиране работна директория). + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +Вероятно ще видите нещо подобно на вашата машина. След като отворите командния ред, обикновено стартирате в домашната директория на вашия потребител. + +* * * + +### Научете повече за команда + +Много команди, които можеш да въведеш в командния ред, имат вградена помощ, която можеш да показваш и да четеш! Например, за да научиш повече за текущата команда на директория: + + + +OS X и Linux имат команда `man`, която ви предоставя помощ за команди. Опитайте `man pwd` и вижте какво пише, или поставете `man` преди други команди, за да видите помощта им. Изходът на `man` обикновено се изписва на страницата. Използвайте интервала, за да преминете към следващата страница, и `q`, за да прекратите прегледа на помощта. + + + + + +Добавянето на `/?` суфикс към повечето команди ще отпечата помощната страница. Може да се наложи да превъртите прозореца на вашата команда нагоре, за да видите всичко. Опитайте `cd /?`. + + + +### Списък на файлове и директории + +И така, какво има в него? Ще е готино да разберем. Да видим: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Промяна на текущата директория + +Сега, нека да отидем на вашата директория Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Отбележи, че името на директорията "Desktop" може да се преведе на езика на вашия Linux акаунт. В такъв случай ще трябва да замените ` Desktop ` с преведеното име; например, `Работен плот` за български език. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Проверете дали наистина е променена: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Ето го! + +> PRO съвет: ако напишете `cd D` и след това натиснете `tab` на клавиатурата си, командният ред автоматично ще попълни останалото име, за да можете да навигирате по-бързо. Ако има повече от една папка, започваща с „D“, натиснете два пъти клавиша `tab`, за да получите списък с опции. + +* * * + +### Създаване на директория + +Какво ще кажете за създаването на тестова директория на вашия работен плот? Можете да го направите по този начин: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% filename %}command-line{% endfilename %} + + > mkdir practice + + + + +Тази малка команда ще създаде папка с името `practice` на вашия работен плот. Можете да проверите дали е там, като погледнете на работния си плот или като изпълните команда `ls` или `dir`! Опитайте. :) + +> PRO съвет: Ако не искате да въвеждате едни и същи команди отново и отново, опитайте да натиснете `стрелката нагоре` и `стрелка надолу` на клавиатурата си, за да преминете през последните използвани команди. + +* * * + +### Упражнение! + +Малко предизвикателство за вас: в новосъздадената си директория `practice` създайте директория, наречена `test`. (Използвайте командите `cd` и `mkdir`.) + +#### Решение: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Поздравления! :) + +* * * + +### Почистване + +Не искаме да оставим бъркотия, така че нека премахнем всичко, което направихме до този момент. + +Първо, трябва да се върнем към Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% filename %}command-line{% endfilename %} + + > cd .. + + + + +Използването на `..` с командата `cd` ще промени текущата ви директория на родителската директория (тоест директорията, която съдържа текущата ви директория). + +Проверете къде се намирате: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Сега е време за изтриване на директорията `practice`: + +> **Внимание**: Изтриването на файлове с помощта на `del`, `rmdir` или `rm` е безвъзвратно, което означава, че *изтритите файлове ще изчезнат завинаги*! Затова бъдете много внимателни с тази команда. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Готово! За да сме сигурни, че е действително изтрита, нека проверим: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### Изход + +Това е засега! Можете спокойно да затворите командния ред. Да го направим по хакерския начин, окей? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Готино, а? :) + +## Обобщение + +Ето обобщение на някои полезни команди: + +| Команда (Windows) | Команда (Mac OS / Linux) | Описание | Пример | +| ----------------- | ------------------------ | -------------------------------- | --------------------------------------------------- | +| exit | exit | затваряне на прозореца | **exit** | +| cd | cd | промяна на директория | **cd test** | +| cd | pwd | показване на текущата директория | **cd** (Windows) или **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (или del) | rm | изтриване на файл | **del c:\test\test.txt** | +| rmdir /S | rm -r | изтриване на директория | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | получете помощ за команда | **cd /?** (Windows) или **man cd** (Mac OS / Linux) | + +Това е само една малка част от командите, които можете да изпълнявате във вашия команден ред, но днес няма да използвате нищо повече от това. + +Ако ви е любопитно, [ss64.com](http://ss64.com) съдържа пълна справка с команди за всички операционни системи. + +## Готови? + +Нека се потопим в Python! \ No newline at end of file diff --git a/bg-BG/intro_to_command_line/open_instructions.md b/bg-BG/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..0bd822d8119 --- /dev/null +++ b/bg-BG/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +В зависимост от вашата версия на Windows и клавиатурата ви, едно от следните трябва да отвори команден прозорец (може да се наложи да експериментирате малко, но не е нужно да изпробвате всички тези предложения): + +- Отиди в менюто или екрана "Старт" и въведи "Команден ред" в полето за търсене. +- Отиди в менюто "Старт" → Windows Система → Команден ред. +- Отиди в менюто Старт → Всички програми → Аксесоари → Команден ред. +- Отидете на стартовия екран, задръжте мишката в долния ляв ъгъл на екрана и щракнете върху стрелката надолу, която се появява (на сензорен екран, вместо това натиснете нагоре от долната част на екрана). Страницата с приложения трябва да се отвори. Кликнете върху командния ред в секцията Windows. +- Задръжте специалния клавиш Windows на клавиатурата си и натиснете клавиша "X". Изберете „Команден ред“ от изскачащото меню. +- Задръжте клавиша на Windows и натиснете клавиша "R", за да получите прозорец "Изпълнение". Въведете "cmd" в полето и щракнете върху бутона OK. + +![Напишете "cmd" в прозореца "Изпълнение"](../python_installation/images/windows-plus-r.png) + +По-късно в това ръководство ще трябва да имате отворени два командни прозореца едновременно. Въпреки това, при някои версии на Windows, ако вече имате един отворен команден прозорец и се опитате да отворите втори, използвайки същия метод, той вместо това ще ви насочи към командния прозорец, който вече имате отворен. Опитайте го сега на вашия компютър и вижте какво ще се случи! Ако получите само един команден прозорец, опитайте някой от другите методи в списъка по-горе. Поне един от тях трябва да доведе до отваряне на нов команден прозорец. + + + + + +Отидете на Applications → Utilities → Terminal. + + + + + +Вероятно е под Applications → Accessories → Terminal или Applications → System → Terminal, но това може да зависи от вашата система. Ако не е там, можете да опитате да го потърсите в Google. :) + + \ No newline at end of file diff --git a/bg-BG/python_installation/README.md b/bg-BG/python_installation/README.md new file mode 100644 index 00000000000..bb84a606d3b --- /dev/null +++ b/bg-BG/python_installation/README.md @@ -0,0 +1,15 @@ +# Да започнем с Python + +Най-накрая сме тук! + +Но първо нека ви разкажем какво е Python. Python е много популярен език за програмиране, който може да се използва за създаване на уебсайтове, игри, научен софтуер, графика и много, много други. + +Python възниква в края на 80-те години и основната му цел е да бъде четен от хора (не само от машини!). Ето защо той изглежда по-прост от другите езици за програмиране, но не се притеснявайте - Python също е наистина мощен! + +# Инсталиране на Python + +> **Забележка** Ако използвате Chromebook, пропуснете тази глава и се уверете, че следвате инструкциите [Настройка на Chromebook](../chromebook_setup/README.md). +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/bg-BG/python_installation/instructions.md b/bg-BG/python_installation/instructions.md new file mode 100644 index 00000000000..fba59ce88ae --- /dev/null +++ b/bg-BG/python_installation/instructions.md @@ -0,0 +1,117 @@ +> За читателите у дома: тази глава е разгледана във видеото [Инсталиране на Python & Редактор на код](https://www.youtube.com/watch?v=pVTaqzKZCdA). +> +> Част от този раздел е базирана на ръководства от Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django е написан на Python. Имаме нужда от Python, за да направим нещо в Django. Нека започнем с инсталирането му! Искаме да инсталирате най-новата версия на Python 3, така че ако имате някоя по-ранна версия, ще трябва да я актуализирате. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Моля, инсталирайте нормален Python по следния начин, дори когато на вашия компютър е инсталиран Anaconda. + + + +Първо проверете дали вашият компютър използва 32-битова версия или 64-битова версия на Windows, в реда "Тип система" на страницата Информация за системата. За да стигнете до тази страница, опитайте един от следните методи: + +* Натиснете едновременно клавиша Windows и клавиша за Пауза/Прекъсване +* Отворете контролния панел от менюто на Windows, след което отворете Система & Сигурност, след това Система +* Натиснете бутона на Windows, след това отворете Настройки> Система> Информация +* Потърсете в менюто "Старт" на Windows "Система информация" За целта щракнете върху бутона Старт или натиснете клавиша Windows, след което започнете да въвеждате `Информация за системата`. То ще започне да прави предложения веднага щом въведете. Изберете правилното, след като се появи. + +Можете да изтеглите Python за Windows от уебсайта https://www.python.org/downloads/windows/. Кликнете върху връзката "Последно издание на Python 3 - Python x.x.x“. Ако вашият компютър работи с **64-битова** версия на Windows, изтеглете **изпълнителния инсталатор Windows x86-64**. В противен случай изтеглете **изпълнителния инсталатор Windows x86**. След като изтеглите инсталатора, трябва да го стартирате (щракнете двукратно върху него) и следвайте инструкциите там. + +Едно нещо, за което трябва да внимавате: По време на инсталацията ще забележите прозорец с надпис „Настройка“. Make sure you tick the "Add Python {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Не забравяйте да добавите Python към Path](../python_installation/images/python-installation-options.png) + +Когато инсталацията приключи, може да видите диалогов прозорец с връзка, която можете да следвате, за да научите повече за Python или за версията, която сте инсталирали. Затворете или отменете този диалог - в това ръководство ще научите повече! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Изтеглете *Mac OS X 64-битов/32-битов инсталатор* файл, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/bg-BG/python_introduction/README.md b/bg-BG/python_introduction/README.md new file mode 100644 index 00000000000..1d07ec54917 --- /dev/null +++ b/bg-BG/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Въведение в Python + +> Част от тази глава е базирана на ръководства от Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Да напишем малко код! + +## Python подкана + +> За читателите у дома: тази част е разгледана във видеото [Python Basics: Integers, Strings, Lists, Variables and Errors](https://www.youtube.com/watch?v=MO63L4s-20U). + +За да започнем да играем с Python, трябва да отворим *командния ред* на вашия компютър. Вече трябва да знаете как да го направите - научихте го в главата [Въведение в командния ред](../intro_to_command_line/README.md). + +След като сте готови, следвайте инструкциите по-долу. + +Искаме да отворим конзола на Python, затова въведете `python` в Windows или `python3` в Mac OS/Linux и натиснете `enter`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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`. + +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +Хубаво! Вижте как отговорът изскочи? Python знае математика! Можете да опитате и други команди като: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +За да извършим експоненциално изчисление, да кажем 2 на степен 3, пишем: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +Забавлявайте се с това за малко и след това се върнете тук. :) + +Както можете да видите, Python е чудесен калкулатор. Ако се чудите какво още можете да направите... + +## Низове + +Какво ще кажете за вашето име? Въведете първото си име в кавички така: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" +'Ola' +``` + +Сега създадохте първия си низ! Това е поредица от знаци, които могат да бъдат обработени от компютър. Низът винаги трябва да започва и завършва с един и същ символ. Това могат да бъдат единични (`'`) или двойни (`"`) кавички (няма разлика!) Кавичките казват на Python, че това, което е вътре в тях, е низ. + +Низовете могат да бъдат нанизани заедно. Опитайте това: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +Можете също да умножите низове с число: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +Ако трябва да поставите апостроф във вашия низ, имате два начина да го направите. + +Използвайки двойни кавички: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +или да избягате от апострофа с обратна черта (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Хубаво, а? За да видите името си с главни букви, напишете: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +Току що използвахте метода `upper` върху вашия низ! Методът (като `upper()`) е поредица от инструкции, които Python изпълнява върху даден обект (`"Ola"`) след като е повикан. + +Ако искате да знаете, от колко на брой букви е вашето име, има функция и за това! + +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +Чудите ли се понякога защо, когато извиквате функции с `.` на края на низа (като `"Ola".upper()`), като понякога извиквате първо функцията и поставяте низа в скоби? Е, в някои случаи функциите принадлежат на обекти, като `upper()`, които могат да се използват само върху низове. В този случай, наричам функцията метод. В други случаи, функциите които не принадлежат към определени типове и могат да бъдат използвани при различни обекти, също като `len()`. Затова даваме `"Ola"` като параметър на функцията `len`. + +### Обобщение + +Добре, достатъчно за низове. Досега научихте за: + +- **подкана** -- писане на команди (код) в Python подкана в резултат дава отговори на езика Python. +- **числа и низове** -- в Python числата се използват за математически операции а низовете за текстови обекти. +- **оператори** – като `+` и `*`, събират стойности за да получат нова +- **функции** – като `upper()` и `len()`, извършващи се върху обектите. + +Това са основите на всеки програмен език, който учите. Готови ли сте за нещо по-сложно? Залагаме, че сте! + +## Грешки + +Нека опитаме нещо ново. Можем ли да вземем дължината на числото по същият начин, по който взехме дължината на нашето име? Напишете `len(304023)` и натиснете `enter`: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +Показа се първата ни грешка! {{ warning_icon }} е начина, по който ще ви показваме, че кода който се опитвате да пуснете няма да работи както се очаква. Грешките (дори и тези, които правим нарочно) са важна част от процеса на учене! + +Казва, че обектът от тип "int" (integers, или още цели числа) нямат дължина. Какво можем да направим сега? Може би да напишем числото ни като низ? Низовете имат дължина, нали така? + +{% filename %}command-line{% endfilename %} + +```python +>>> len(str(304023)) +6 +``` + +Работи! Използвахме функцията `str` във функцията `len`. `str()` преобразува всичко в низове. + +- Функцията `str` преобразува нещата в **низове** +- Функцията `int` преобразува нещата като **цели числа** + +> Важно: можем да преобразуваме числа в текст, но не можем да направим обратното -- както и да е какво би било `int('hello')`? + +## Променливи + +Важно понятие в програмирането са променливите. Променливата е нищо повече от име, което може да се използва по-късно в програмата. Програмистите ползват тези променливи да запазват данни. Това прави кода им по-четлив, така че не се налага да запомнят какви са тези неща. + +Нека кажем, че искаме да създаде променлива с име `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +Пишем name равно на Ola. + +Ако забелязахте, програмата ви не върна нищо както преди това. Как да разберем, че променливата съществува? Напишете `name` и натиснете бутона `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Ихууу! Първата ти променлива! :) Винаги може да я промениш към какво се отнася: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +Може да я използвате и във функции: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Страхотно, нали? Сега, променливите могат да са какво ли не -- също така и числа! Пробвайте това: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +Но какво ако използваме грешното име Можете ли да отгатнете какво ще се случи? Нека опитаме! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +Грешка! Както виждате, Python има различни видове грешки, като тази се казва **NameError**. Python винаги ще ви дава тази грешка, ако се опитвате да използвате променлива, която все още не е дефинирана. Ако попаднете на тази грешка по-късно, вижте дали не сте сбъркали при писането на някое от имената. + +Поиграйте се малко с това и вижте какво може да правите! + +## Фунцкията print + +Пробвайте това: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` + +Когато напишете `name`, интерпретатор на Python отговаря със низово *образ* на променливата 'name', което е буквите M-a-r-i-a, обградени от единични кавички. Когато кажем `print(name)`, Python ще "отпечата" съдържанието на променливата на екрана, без кавичките, което е по-прилежно. + +Както ще видим по-късно `print()` също е полезен, когато искаме да отпечатаме неща от функциите, или когато искаме да отпечатаме неща на няколко реда. + +## Листове + +Освен низовете и целите числа, Python има всякакви видове типове обекти. Сега ще въведем една от тях наречена **list**. Листоверте са точно това, което си мислите, че са: обекти, които са листове от други обекти. :) + +Давайте нататък и създайте лист: + +{% filename %}command-line{% endfilename %} + +```python +>>> [] +[] +``` + +Да, това е празен лист. Не е много полезен нали? Нека създадем лист с лотарийни номера. Не искаме да се повтаряме постоянно, така че ще използваме променлива: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +И така, имаме лист! Какво можем да правим с него? Нека видим колко лотарийни числа има в листа? Имате ли си на идея коя функция може да се използва за това? Това вече го знаете! + +{% filename %}command-line{% endfilename %} + +```python +>>> len(lottery) +6 +``` + +Да! `len()` може да ви даде броя на обектите в листа. Много удобно, нали? Може би и ще го сортираме: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.sort() +``` + +Това не връща нищо, само променя реда, в който числата са показани в листа. Нека го отпечатаме отново и видим какво се случва: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +Както се вижда, числата в листа са вече подредени от по-малката към по-голямата стойност. Поздравления! + +Може би искаме да направим обратното? + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +Ако искате да добавите нещо към вашия лист, може да го направите като напишете следната команда: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +Ако искате да покажете само първото число, може да направите това като използвате **индекси**. Индекса е номерът, който казва къде в листа се появява елемента. Програмистите предпочитат да започват броенето от 0, така че първият обект в листа е с индекс 0, следващия е с 1 и т.н. Опитайте това: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` + +Както може да видите, можете да достъпите различни обекти от листа си като използвате името на листа и индекс със квадратни скоби. + +За да премахнете нещо от листа си ще трябва да използвате **индексите**, които научихме по-горе и метода `pop()`. Нека пробваме пример и затвърдим това, което научихме до момента: ще отстраним първото число от листа ни. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +Работи безупречно! + +За повече веселба, пробвайте други индекси: 6, 7, 1000, -1, -6 or -1000. Пробвайте се да предположите какъв би могъл да е резултата от командата. Имат ли смисъл резултатите? + +Можете да намерите лист с всички възможни методи в тази глава от документацията на Python: https://docs.python.org/3/tutorial/datastructures.html + +## Речници + +> За читателите у дома: тази част е показана във видеото [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c). + +Речникът е подобен на лист, но вие получавате достъп до стойности, като търсите ключ вместо числов индекс. Ключът може да бъде всеки низ или число. Синтаксисът за дефиниране на празен речник е: + +{% filename %}command-line{% endfilename %} + +```python +>>> {} +{} +``` + +Това показва, че в момента създадохте празен речник. Ура! + +Сега, опитайте се да напишете следната команда (опитайте се да заместите със своя информация): + +{% filename %}command-line{% endfilename %} + +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` + +С тази команда, току що създадохте променлива с име `participant` с три елемент-стойност (keys-value) двойки. + +- Ключът `name` се сочи към стойността `'Ola'` (`низов` обект), +- `country` сочи към `'Poland'` (друг `низ`), +- and `favorite_numbers` се отнася за `[7, 42, 92]` (`лист` с три числа в него). + +Може да проверите съдържанието на всеки от елементите с този синтаксис: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(participant['name']) +Ola +``` + +Виждате ли, подобно е на лист. Но не е необходимо да помните индекса -- само името. + +Какво се случва, когато попитаме Python за стойността на елемент, който не съществува? Можете ли да познаете? Нека опитаме и видим: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` + +Вижте, друга грешка! Тази е **KeyError**. Python е много услужлив и ти казва, че елемент `'age'` не съществува в този речник. + +Кога да използвате речник и кога лист? Това е добър въпрос. Помислете за отговор преди да видите следващия ред. + +- Ако имате нужда просто от подредена последователност от елементи? Ползвайте лист. +- Ако трабва да асоциирате стойности с елементи, които искате да може да ги видите на по-късен етап (чрез елемент - by key)? Използвайте речник. + +Речниците са като листове, но *непостоянни*, което означава, че могат да бъдат променени след като бъдат създадени. Може да добавяте нови двойки елемент-стойност към речника след като е създаден ето така: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +Надявам се да има смисъл това което правим досега. :) Готови ли сте за още веселба с речниците? Прочетете някои невероятни неща. + +Можете да използвате метода `pop()` да изтриете елемент от речника. Да кажем, че искаме да премахнем въведението, което се отанся за елемента `'favorite_numbers'`, напишете следната команда: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Както се вижда, двойката елемент-стойност отнасяща се за 'favorite_numbers' беше премахната. + +Както и това, можете да промените стойността, която отговаря на вече създаден елемент в речника. Напишете това: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Както виждате, стойността на елемента `'country'` беше променен от `'Poland'` на `'Germany'`. :) Вълнуващо? Ураа! Току що научихте още едно невероятно нещо. + +### Обобщение + +Страхотно! Вече знаете много за програмирането. В тази последна част научихте за: + +- **грешки** -- знаете как да четете и разбирате грешките които се показват, ако Python не разбира командата която сте задали +- **променливи** – имена на обектите, които ви позволяват да пишете код по-лесно и да правят кода ви по-четлив +- **листове** –листовете са обекти запазени в определен ред +- **речници** – обекти запазени като двойки от елемент-стойност (key-value pairs) + +Вълнувате ли се за следващата част? :) + +## Сравняване на неща + +> За читателите у вома: тази част е показана във видеото [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4). + +Голяма част от програмирането включва сравняване на неща. Какво е най-лесното нещо което може да се сравни? Числата! Нека видим как работи: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. Nice, huh? + +Чудите ли се защо използвахме два знака за равно `==` един до друг за да сравним дали числата са равни? Използваме едно равно `=` за да причислим стойност на променливите. Винаги, ама **винаги** трябва да иползваме две от тях – `==` – ако искаме да проверим дали две неща са равни едно на друго. Можем също така да кажем, че не искаме двете неща да са равни едно на друго. Затова, използваме символа `!=`, както е показано в примера по-горе. + +Дайте на Python още две задачки: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +Виждали сме `>` и `<`, но какво означават `>=` и `<=`? Четем ги по този начин: + +- x `>` y означава: x е по-голямо от y +- x `>` y означава: x е по-малко от y +- x `<=` y означава: x е по-малко или равно на y +- x `>=` y означава: x е по-голямо или равно на y + +Страхотно! Искате ли да направите още нещо? Пробвайте това: + +{% filename %}command-line{% endfilename %} + +```python +>>> 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: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and 'str' +``` + +Тук виждате, че точно както в израза, Python не е в състояние да сравни число (`int`) и низ (`str`). Вместо това ни показва грешка **TypeError** и ни казва, че двата типа не могат да бъдат сравнени. + +## Булеви променливи + +По между другото, току що научихте за нов тип обект в Python. Нарича се **Булев (Boolean)**. + +Има само два вида булеви променливи: + +- True +- False + +Но за Python да разбере това, винаги трябва да пишете 'True' (като първата буква е главна, а следващите малки). **true, TRUE, and tRUE няма да работят – само True е правилно.** (Същото се отнася и до 'False'.) + +Булевите стойности могат също да са променливи! Вижте тук: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +Може също да го направите по този начин: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Практикувайте и се повеселете с булевите стойности като се опитате да напишете следните команди: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Поздраления! Булевите стойности са едни от най-готините неща в програмирането, и ти току що се научи как да ги използваш! + +# Запази! + +> За читателите у дома: тази част е показана във видеото [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk) + +До тук писахме всичкия си python код в интерпретатора, който ни ограничава да използваме само едни ред да впишем кода. Обикновено програмите са запазени във файлове и после изпълнени от **интерпретатора** или **компилатора** ни. Досега пускахме нашите програми по една на ред в Python интерпретатора. Ще са ни необходими малко повече редове от код за следващите няколко задачи, затова бързо ще направим това: + +- Излезем от Python интерпретатора +- Отворим редактор за текс по избор +- Запазим малко код в нов python файл +- Пуснете го! + +За да излезнем от Python интерпретатора, който използвахме, пише следната функция `exit()` + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` + +Това ще те завърне обратно в командния ред. + +По-рано избрахме нашия редактор от секцията за [code editor](../code_editor/README.md). Сега ще трябва да отворим редактора и да запишем малко код в нов файл (или ако използваш Chromebook, създай нов файл в облачната IDE и отвори файла, който ще бъде във включения редактор на код): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +Очевидно, вече сте по-обиграни Python разработчици, така че напишете код, който научихте днес. + +Сега трябва да запазим файла и да му дадем описателно име. Нека наречем файла **python_intro.py** и го запазим на началния си екран. Можем да именуваме файла си както пожелаем, но е важно да сме сигурни, че завършва на **.py**. Разширението **.py** казва на операционната система, че това е **Python executable file** и Python може да го обработи. + +> **Забележка:** Трябва да забелязахте, че едни от най-готините неща в редактора са: цветовете! В конзолата Python всичко беше в един и същ цвят; сега трябва да видите, че функцията `print` е различен цвят от низа. Това се нарича "syntax highlighting", и е много полезна добавка когато пишем код. Цветът на нещата ще ви даде подсказки, като например незатворени низове или печатни грешки в име на ключова дума (като `def` във функция, както ще видим по-долу). Това е една от причините да изполваме редактор за писане на код. :) :) + +Файлът е записан, време е да го стартираш! Използвайки уменията, които си научила в секцията за командния ред, използвай терминала за да **промениш директориите** на работния плот. + + + +На Mac, командата ще излгежда по този начин: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +На Linux, ще изглежда така: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Помнете, че думата "Desktop" може да е преведена на вашия език.) + + + + + +На Windows Command Prompt ще изглежда ето така: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +И на Windows Powershell ще изглежда така: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +Ако се затруднявате, поискайте помощ. Затова са менторите! + +Сега ползвайте Python за да изпълни кода във файла ето така: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hello, Django girls! + + +Забележка: на Windows 'python3' не е разпознат като команда. Вместо това, използвайте 'python' за да стартирате файла: + +{% filename %}command-line{% endfilename %} + +```python +> python python_intro.py +``` + +Браво! Току що пуснахте първата си програма на Python, която беше запазена на файл. Чувствате ли се страхотно? + +Сега може да се прехвърлим на по-важно средство в програмирането: + +## If … elif … else + +Много неща в кода трябва да се изпълнят само ако са преминали определени условия. Затова Python има нещо, наречено **if условна конструкция**. + +Заместете кода във файла си **python_intro.py** с това: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: +``` + +Ако запазим и стартираме файла ще видим грешка като тази: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +Python очаква от нас да дадем следващи инсктрукции какво да се изпълни в условието `3 > 2` за да бъде вярно (или `True` за същата цел). Нека накараме Python да отпечата “It works!”. Променете кода си във файла с това: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: + print('It works!') +``` + +Забелязахте ли как изписахме следващия ред от код с 4 празни места навътре? Трябва да направим това за да може Python да знае, кой код да изпълни в случай, че е вярно условието. Може да използвате едно празно място, но почти всеки Python програмист използва 4, тъй като изглежда по-прилежно. Използването на бутона Tab също се равнява на 4 места, ако сте направили редактора си да прави така. Когато направите избор не го променяйте! Ако вече сте използвали 4 места за в бъдеще ползвайте 4 места - в противен случай може да попаднете на затруднения. + +Запазете и го стартирайте отново: + +{% filename %}command-line{% endfilename %} + +```python +$ python3 python_intro.py +It works! +``` + +Забележка: Помнете, че на Windows, 'python3' не се разпознава като команда. От сега нататък, заместете 'python3' с 'python' за да изпълните файла. + +### Какво ако условието не е вярно (True)? + +В предходните примери, кода се изпълняваше само ако условието е вярно (True). Но Python има също `elif` и `else` условия: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 5 > 2: + print('5 is indeed greater than 2') +else: + print('5 is not greater than 2') +``` + +Когато това се изпълни ще се отпечата: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +Ако 2 беше по-голямо число от 5, тогава втората команда щеше да се изпълни. Нека видим как работи `elif` : + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +и се изпълнява: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hey Sonja! + + +Видяхте ли какво се случи там? `elif` ви даде възможност да добавите още едно условие в случай, че предното се провали. + +Може да добавяте колкото си искате `elif` условия след първоначалното `if` условие. Например: + +{% 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 преминава и тества през всеки ред и отпечатва: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Perfect, I can hear all the details + + +## Коментари + +Коментрите са редове, започващи с `#`. Може да пишете каквото искате след `#` и Python ще го игнорира. Коментарите са направени да правят кода по-лесен за четене и разбиране от другите хора. + +Нека видим как изглежда: + +{% 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!") +``` + +Не е необходимо да пишете коментар за всеки ред от код, но те са много подходящи да обяснят какво прави самия код, или да дадат обобщение, когато се прави нещо сложно. + +### Обобщение + +В последните няколко упражнения научихте как да: + +- **сравнявате** – в Python може да сравнявате като използвате `>`, `>=`, `==`, `<=`, `<` и `and`, `or` оператори +- използвате **булеви променливи** – типа на обекта може да приема само две стойности: `True` или `False` +- **запазвате файлове** – запазване на кода във файлове, така че да могат да се изпълняват по-големи програми. +- използвате **if … elif … else** – условна конструкция, която ви позволява да изпълнявате код когато определени условия се изпълнят. +- пишете **коментари** - редовете в Python, които не се изпълняват и дават пояснения за кода ви + +Време е за последната част от тази глава! + +## Вашите собствени функции! + +> За читателите у дома: тази част е показана във видеото [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0). + +Помните ли функциите като `len()`, които изпълнихте в Python? Така, добри новини - сега ще научите как да напишете свои фукции! + +Функцията е последователност от инструкции, така че Python да може да я изпълнин. Всяка функция в Python започяа с ключовата дума `def`, с което се дава име на функцията и може да има няколко параметъра. Нека пробваме. Заместете кода във файла **python_intro.py** със следното: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Добре, първата ви функция е готова! + +Може би се чудите защо написахме името на функцията в края на файла. Когато пишем `def hi():` и следващите редове започват по-навътре, това оказва какво трябва да направи функцията `hi()`. Python ще прочете и запомни тези инструкции, но няма да изпълни все още функцията. За да кажем на Python да изпълни функцията, трябва да извикаме вункцията с `hi()`. Python чете файла и изпълнява от горе до долу, затова трябва да дефинираме функцията преди да сме я повикали. + +Нека го стартираме и видим какво се случва: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Забележка: ако не работи не се паникьосвайте! Резултатът ще ви помогне да разберете защо: + +- Ако получите грешка `NameError`, това най-вероятно означава, че сте направили грешка при писането, такаче трябва да проверите дали имената са същите при създаването на функцията `def hi():` и когато я извиквате `hi()`. +- Ако получите грешка `IndentationError`, вижте дали двата реда с функцията `print` са отместени на едно и също растояние: python иска кода във функцията да бъде безупречно подреден. +- Ако на изхода няма нищо, проверете дали последното `hi()` *не е* отместено - ако е , тази част също ще се превърне в част от функцията и никога няма да се изпълни + +Нека съставим първата си функция с параметри. Ще променим предния пример - функцията, която казва 'hi' на човека, който пуска програмата - с име: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): +``` + +Както се вижда, дадохме на функцията си стойност, която нарекохме `name`: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +hi() +``` + +Запомнете: `print` функцията е поместена 4 места навътре спрямо `if` условието. Това е така, защото функцията се изпълнява, ако е изпълнено условието. Нека видим как работи: + +{% filename %}{{ warning_icon }} 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' + + +Опаа, грешка. За щастие, Python ни показва много полезно съобщение за грешката. Казва ни, че фукнцията `hi()` (която ние дефинирахме) има аргумент, който се изисква (с име `name`) и че сме забравили да го приложим, когато извикваме фунцкията. Нека оправим това в края на файла: + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Ola") +``` + +И да стартираме отначало: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Ola! + + +А ако сменим името? + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Sonja") +``` + +И стартираме отново: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Sonja! + + +Сега, какво мислите, че ще стане ако напишете ново име? (Не Ola или Sonja.) Опитайте и вижте дали сте прави. Трябва да отпечата това: + +{% filename %}command-line{% endfilename %} + + Hi anonymous! + + +Това е страхотно, нали? При това не трбва да се повтаряте всеки път, когато смените името на човека, който функцията трябва да поздрави. Затова са ни необходими функциите - никога да не повтаряш кода си! + +Нека опитаме нещо по-хитро - имаме повече от две имена и писането на условия за всяко едно от тях ще отнеме много време, нали така? Заместете съдържание на файла си със следното: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Нека извикаме кода: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + + +Поздравления! Току що научихте как да пишете функции! :) + +## Цикли + +> За читателите у дома: тази част е показана във видеото [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) + +Това вече е последната част. Мина бързо, нали? :) + +Програмистите не обичат да е повтарят. Програмирането се отнася до автоматизация, така че не искаме да поздравяваме всеки човек по име като изписваме за всеки по отделно, нали? Ето къде циклите идват в употреба. + +Все още си спомняте листовете? Нека направим лист с момичета: + +{% filename %}python_intro.py{% endfilename %} + +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + +Искаме да поздравим всяка една от тях по име. Имаме функцията `hi` да направи това, така че нека я използваме в цикъл: + +{% filename %}python_intro.py{% endfilename %} + +```python +for name in girls: +``` + +Конструкцията `for` се държи подобно на конструкцията `if`; кода под него трябва да е отместен с четири места навътре. + +Ето целия код, който трябва да е във файла: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('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 + + +Както виждате всичко, което сложите вътре във `for` конструкцията с отместването ще бъде повторено за всеки елемент от листа `girls`. + +Може също да използвате `for` цикъл за числа като използвате фунцкията `range` : + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Което ще отпечата: + +{% filename %}command-line{% endfilename %} + + 1 + 2 + 3 + 4 + 5 + + +`range` е функция, която създава лист от номера едно след друго (тези номера са дадени от вас като стойности). + +Забележете, че втория параметър, който сте дали не се включва в листа с показаните числа от Python (което означава, че `range(1, 6)` брои от 1 до 5, без да включва числото 6). Това е така, защото "range" е полу-отворена функция, което означава, че включва първата стойност, но не и последната. + +## Обобщение + +Това е! **Ти си върха!** Това беше сложна глава, така че трябва да сте горди със себе си. Ние определено сме горди с това, което постигнахте досега! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +Може би искате да направите нещо друго за кратко - разтягане, разходка, да ви отпочинат очите - преди да отидем към следващата глава. :) + +![Кексче](images/cupcake.png) \ No newline at end of file diff --git a/bg-BG/template_extending/README.md b/bg-BG/template_extending/README.md new file mode 100644 index 00000000000..57c12c2da81 --- /dev/null +++ b/bg-BG/template_extending/README.md @@ -0,0 +1,151 @@ +# Разширяване на шаблона + +Друго хубаво нещо, което Django има за вас, е **разширяване на шаблона**. Какво означава това? Това означава, че можете да използвате същите части на вашия HTML за различни страници на вашия уебсайт. + +Шаблоните помагат, когато искате да използвате една и съща информация или оформление на повече от едно място. Не е нужно да се повтаряте във всеки файл. И ако искате да промените нещо, не е необходимо да го правите във всеки шаблон, само в един! + +## Създайте основен шаблон + +Базовият шаблон е най-основният шаблон, който разширявате на всяка страница от вашия уебсайт. + +Нека създадем `base.html` файл в `blog/templates/blog/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +След това го отворете в редактора на кода и копирайте всичко от `post_list.html` във `base.html` файл, като този: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +След това в `base.html` заменете съдържанието в секцията `` (всичко между `` и ``) с това: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}Може да забележите, че това замени всичко от `{% for post in posts %}` до `{% endfor %}` с: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +Но защо? Току-що създадохте `block`! Използвахте шаблонния маркер `{% block %}`, за да направите област, в която да бъде вмъкнат HTML код. Този HTML код ще идва от друг шаблон, който разширява този шаблон (`base.html`). Ще ви покажем как да направите това след малко. + +Сега запишете `base.html` и отворете вашия `blog/templates/blog/post_list.html` отново в редактора на кода. {% raw %} Ще премахнете всичко по-горе `{% for post in posts %}` и под `{% endfor %}`. Когато приключите, файлът ще изглежда така:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +Искаме да използваме това като част от нашия шаблон за всички съдържателни блокове. Време е да добавите блокови тагове към този файл! + +{% raw %}Искате вашият маркер за блока да съвпада с маркера във вашия `base.html` файл. Освен това искате той да включва всички кодове, които принадлежат във вашите блокове на съдържание. За целта поставете всичко между `{% block content %}` и `{% endblock %}`. Ето така:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Остана само едно нещо. Трябва да свържем тези два шаблона заедно. За това става въпрос в разширяващите се шаблони! Ще направим това, като добавим маркер за разширения в началото на файла. Ето така: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Това е! Запазете файла и проверете дали уебсайтът ви все още работи правилно. :) + +> Ако получите грешката `TemplateDoesNotExist`, това означава, че няма `blog/base.html` файл и имате `runserver` работещ в конзолата. Опитайте се да го спрете (като натиснете Ctrl + C - клавишите Control и C заедно) и го рестартирайте, като изпълните команда `python manage.py runserver`. \ No newline at end of file diff --git a/bg-BG/whats_next/README.md b/bg-BG/whats_next/README.md new file mode 100644 index 00000000000..896922a2b32 --- /dev/null +++ b/bg-BG/whats_next/README.md @@ -0,0 +1,43 @@ +# Какво следва? + +Поздравете се! **Ти си напълно страхотен**. Гордеем се! <3 + +### Какво да правим сега? + +Направете почивка и се отпуснете! Току-що направихте нещо наистина огромно. + +След това, не забравяйте да следвате Django Girls във [ Facebook ](http://facebook.com/djangogirls) или [ Twitter ](https://twitter.com/djangogirls). + +### Можете ли да препоръчате допълнителни ресурси? + +Да! Има *много* онлайн ресурси за научаване на всякакви умения за програмиране - може да бъде доста трудно да разберете как да продължите по-натам, но не се безспокойте. Каквито и да бяха интересите ви преди да дойдете на Django Girls и каквито и интереси сте развили по време на ръководството, ето някои безплатни ресурси (или ресурси с големи безплатни компоненти), които можете да използвате, за да стигнете до това, което искате. + +#### Django + +- Другата ни книга, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Официалното ръководство на Django](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Първи стъпки с видео уроци на Django](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) - някои видео лекции могат да бъдат одитирани безплатно и можете да спечелите сертификат Coursera, като вземете тези курсове + +#### HTML, CSS и JavaScript + +- [Курс за уеб разработка на Codecademy](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Курс по Python на Codecademy](https://www.codecademy.com/learn/learn-python) +- [Курс по Python на Google](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – първоначалните упражнения са безплатни +- [New Coder tutorials](http://newcoder.io/tutorials/) - това са различни практически примери за това как можете да използвате Python +- [ edX ](https://www.edx.org/course?search_query=python) - можете да участвате в повечето курсове безплатно, но ако искате сертификат или по-голяма квалификация, това ще струва пари +- [Python специализация на Coursera](https://www.coursera.org/specializations/python) - можете да участвате в няколко видео лекции безплатно и можете да спечелите сертификат на Coursera, като вземете тези курсове +- [Python for Everybody](https://www.py4e.com/) - безплатна и отворена версия на специализирания Python Coursera за всеки + +#### Работа с данни + +- [Курсът по научни данни на Codecademy](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) - можете да участвате в повечето курсове безплатно, но ако искате сертификат или по-голяма квалификация, това ще струва пари +- [Dataquest](https://www.dataquest.io/) - първите 30 "мисии" са безплатни + +Нямаме търпение да видим какво ще изградите след това! \ No newline at end of file diff --git a/bg/GLOSSARY.md b/bg/GLOSSARY.md new file mode 100644 index 00000000000..2e928dda548 --- /dev/null +++ b/bg/GLOSSARY.md @@ -0,0 +1,3 @@ +# code editor + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/bg/README.md b/bg/README.md new file mode 100644 index 00000000000..01736ae0502 --- /dev/null +++ b/bg/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) + +## Introduction + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/bg/SUMMARY.md b/bg/SUMMARY.md new file mode 100644 index 00000000000..7a45700a27d --- /dev/null +++ b/bg/SUMMARY.md @@ -0,0 +1,27 @@ +# Summary + +* [Introduction](README.md) +* [Installation](installation/README.md) +* [Installation (chromebook)](chromebook_setup/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) +* [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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/bg/chromebook_setup/README.md b/bg/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/bg/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/bg/chromebook_setup/instructions.md b/bg/chromebook_setup/instructions.md new file mode 100644 index 00000000000..809281456d3 --- /dev/null +++ b/bg/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/bg/code_editor/README.md b/bg/code_editor/README.md new file mode 100644 index 00000000000..404011f1b7d --- /dev/null +++ b/bg/code_editor/README.md @@ -0,0 +1,11 @@ +# Code editor + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +You're about to write your first line of code, so it's time to download a code editor! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/bg/code_editor/instructions.md b/bg/code_editor/instructions.md new file mode 100644 index 00000000000..074cd86196e --- /dev/null +++ b/bg/code_editor/instructions.md @@ -0,0 +1,31 @@ +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 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 and 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. :) \ No newline at end of file diff --git a/bg/css/README.md b/bg/css/README.md new file mode 100644 index 00000000000..04d5996ae52 --- /dev/null +++ b/bg/css/README.md @@ -0,0 +1,304 @@ +# 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 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? 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: https://getbootstrap.com/ + +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: + +{% 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! + +![Figure 14.1](images/bootstrap1.png) + +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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +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. 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 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 + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +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. :) 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 be overriden by 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 %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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 + +``` + +And now add a class `post` to your `div` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/bg/deploy/README.md b/bg/deploy/README.md new file mode 100644 index 00000000000..b44e2eaaf73 --- /dev/null +++ b/bg/deploy/README.md @@ -0,0 +1,260 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ 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) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. + +Hit **Save** and then go back to the **Web** tab. + +We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. + +## Debugging tips + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: + +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. + +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. + +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? + +- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. + +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +And remember, your coach is here to help! + +# You are live! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! \ No newline at end of file diff --git a/bg/deploy/install_git.md b/bg/deploy/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/bg/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/bg/deploy/signup_pythonanywhere.md b/bg/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/bg/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/bg/django/README.md b/bg/django/README.md new file mode 100644 index 00000000000..c62c145305b --- /dev/null +++ b/bg/django/README.md @@ -0,0 +1,27 @@ +# What is Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +Of course, the description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will simply start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/bg/django_admin/README.md b/bg/django_admin/README.md new file mode 100644 index 00000000000..46a5afbb500 --- /dev/null +++ b/bg/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/bg/django_forms/README.md b/bg/django_forms/README.md new file mode 100644 index 00000000000..1d9efebffe4 --- /dev/null +++ b/bg/django_forms/README.md @@ -0,0 +1,447 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? + +## URL + +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```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` we add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## Security + +Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to Github: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/bg/django_installation/README.md b/bg/django_installation/README.md new file mode 100644 index 00000000000..7834993e063 --- /dev/null +++ b/bg/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/bg/django_installation/instructions.md b/bg/django_installation/instructions.md new file mode 100644 index 00000000000..0bc080f7055 --- /dev/null +++ b/bg/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/bg/django_models/README.md b/bg/django_models/README.md new file mode 100644 index 00000000000..7aa11d11732 --- /dev/null +++ b/bg/django_models/README.md @@ -0,0 +1,199 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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 + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/bg/django_orm/README.md b/bg/django_orm/README.md new file mode 100644 index 00000000000..31c47f27764 --- /dev/null +++ b/bg/django_orm/README.md @@ -0,0 +1,218 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Chaining QuerySets + +You can also combine QuerySets by **chaining** them together: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/bg/django_start_project/README.md b/bg/django_start_project/README.md new file mode 100644 index 00000000000..fe1abc7ca9a --- /dev/null +++ b/bg/django_start_project/README.md @@ -0,0 +1,202 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![It worked!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/bg/django_templates/README.md b/bg/django_templates/README.md new file mode 100644 index 00000000000..263eb1fd835 --- /dev/null +++ b/bg/django_templates/README.md @@ -0,0 +1,106 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/bg/django_urls/README.md b/bg/django_urls/README.md new file mode 100644 index 00000000000..c491b27de5c --- /dev/null +++ b/bg/django_urls/README.md @@ -0,0 +1,129 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![Url](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Regex + +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. + +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: + +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern + +Anything else in the URL definition will be taken literally. + +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. + +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: + +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/bg/django_views/README.md b/bg/django_views/README.md new file mode 100644 index 00000000000..07afe091a52 --- /dev/null +++ b/bg/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/bg/dynamic_data_in_templates/README.md b/bg/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..807bb666ebc --- /dev/null +++ b/bg/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/bg/extend_your_application/README.md b/bg/extend_your_application/README.md new file mode 100644 index 00000000000..0bae760be7c --- /dev/null +++ b/bg/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: + +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? Of course: adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`. + +It will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ 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 %} + +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 --all . + $ git status + $ 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/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/bg/how_the_internet_works/README.md b/bg/how_the_internet_works/README.md new file mode 100644 index 00000000000..efd95c3f4b2 --- /dev/null +++ b/bg/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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. + +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![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 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - 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 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, 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 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! \ No newline at end of file diff --git a/bg/html/README.md b/bg/html/README.md new file mode 100644 index 00000000000..004985089c2 --- /dev/null +++ b/bg/html/README.md @@ -0,0 +1,213 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Add the following to your template file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +

Hi there!

+

It works!

+ +``` + +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 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `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, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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.

+
+ + +``` + +We've created three `div` sections here. + +* 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to Github + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% 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: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **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): + +{% 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. + +{% 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: + +{% 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 + $ git pull + [...] + + +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. + +* 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. :) \ No newline at end of file diff --git a/bg/install_git.md b/bg/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/bg/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/bg/installation/README.md b/bg/installation/README.md new file mode 100644 index 00000000000..a7c627136c8 --- /dev/null +++ b/bg/installation/README.md @@ -0,0 +1,58 @@ +# 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 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. \ No newline at end of file diff --git a/bg/instructions.md b/bg/instructions.md new file mode 100644 index 00000000000..30bd493b11b --- /dev/null +++ b/bg/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/bg/intro_to_command_line/README.md b/bg/intro_to_command_line/README.md new file mode 100644 index 00000000000..5fb6d48dd1f --- /dev/null +++ b/bg/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +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. :) + +> 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 by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/bg/python_installation/README.md b/bg/python_installation/README.md new file mode 100644 index 00000000000..93f81cb42d9 --- /dev/null +++ b/bg/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/bg/python_installation/instructions.md b/bg/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/bg/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/bg/python_introduction/README.md b/bg/python_introduction/README.md new file mode 100644 index 00000000000..c1642302532 --- /dev/null +++ b/bg/python_introduction/README.md @@ -0,0 +1,1062 @@ +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.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. + +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. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, simply type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% 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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% 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! + +{% 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% 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 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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 + +{% 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!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/bg/signup_pythonanywhere.md b/bg/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/bg/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/bg/template_extending/README.md b/bg/template_extending/README.md new file mode 100644 index 00000000000..35997f913d3 --- /dev/null +++ b/bg/template_extending/README.md @@ -0,0 +1,147 @@ +# Template extending + +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. + +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 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 + + +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 %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. 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' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/bg/whats_next/README.md b/bg/whats_next/README.md new file mode 100644 index 00000000000..fbb1d2a7d6e --- /dev/null +++ b/bg/whats_next/README.md @@ -0,0 +1,25 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](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](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). + +Later on, you can try the resources listed below. They're all very recommended! + +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/bn-BD/GLOSSARY.md b/bn-BD/GLOSSARY.md new file mode 100644 index 00000000000..8c6897995f8 --- /dev/null +++ b/bn-BD/GLOSSARY.md @@ -0,0 +1,3 @@ +# কোড এডিটর + +কোড এডিটর এমন একটি অ্যাপ্লিকেশন যা আপনাকে আপনার কোড সংরক্ষণ করতে দেয় যাতে আপনি পরে এটিকে ফিরে পেতে সক্ষম হন। আপনি [কোড এডিটর অধ্যায়](./code_editor/README.md) থেকে শিখা শুরু করতে পারেন। \ No newline at end of file diff --git a/bn-BD/README.md b/bn-BD/README.md new file mode 100644 index 00000000000..202baf6e444 --- /dev/null +++ b/bn-BD/README.md @@ -0,0 +1,51 @@ +# জ্যাঙ্গো গার্লস টিউটোরিয়াল + +[![গিটার ](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> এই টিউটোরিয়ালটি Creative Common Attribution-ShareAlike 4.0 International লাইসেন্স-এর মাধ্যমে প্রকাশিত হয়েছে। লাইসেন্সটির প্রতিলিপি দেখতে ভিজিট করুনঃ https://creativecommons.org/licenses/by-sa/4.0 + +## স্বাগতম + +সবাইকে জ্যাঙ্গো গার্লস বাংলা টিউটোরিয়াল এ স্বাগত! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## ভূমিকা + +তোমার কি এই রকম মনে হয়েছে যে, পৃথিবীতে প্রযুক্তি অনেক এগিয়ে চলছে , আর তুমি এটা থেকে অনেক পিছিয়ে পড়ছো? তুমি কি কখনো অবাক হয়েছো যে, কিভাবে একটি ওয়েবসাইট তৈরি হয়, কিন্তু কোন ভাল অনুপ্রেরণা না থাকায় তুমি এটা তৈরি করতে পারছো না? বর্তমান সফটওয়্যার শিল্প কি আপনার নিজের সামান্য কোনো সফটওয়্যার বানানোর জন্যও অনেক জটিল মনে হয়েছে? + +ঠিক আছে, তোমার জন্য আমাদের পক্ষ থেকে একটি সুখবর আছে !! প্রোগ্রামিং যতটা কঠিন ভাবছো আসলে তা এত কঠিন নয় বরং এটি কিভাবে আরো আনন্দদায়ক করা যায় তা তোমাকে আমরা দেখাবো। + +এই টিউটোরিয়ালটি তোমাকে রাতারাতি প্রোগ্রামার বানিয়ে দিবে না। তুমি যদি এই বিষয়ে ভাল হয়ে চাও, তোমাকে এটি শিখতে হবে এবং অনুশীলন করতে হবে, এরজন্য তোমার অনেক মাস বা বছর লাগতে পারে । কিন্তু আমরা তোমাকে দেখাবো প্রোগ্রামিং বা ওয়েবসাইট তৈরি করা আসলে এত জটিল কিছু নয় যা তুমি ভাবছো । আমরা প্রতিটি ক্ষুদ্র ক্ষুদ্র জিনিস তোমাকে ব্যাখা করার চেষ্টা করবো, যাতে তুমি এই প্রযুক্তি রিলেটেড কোন কিছুকে আর ভয় না পাও । + +আমরা আশা করি, আমরা যেভাবে এই প্রযুক্তির প্রতিটি স্পন্দনকে ভালবাসি, সেভাবে তুমি ভালবাসবে । + +## তুমি এই টিউটোরিয়াল জুড়ে কি শিখবে? + +যখন তুমি এই টিউটোরিয়াল শেষ করবে, তখন তোমার কাছে তোমার ওয়েব এপ্লিকেশন থাকবেঃ তোমার নিজের ব্লগ। এরপর তোমাকে দেখাবো তুমি কিভাবে এটি অনলাইনে প্রকাশ করবে, যাতে সবাই তোমার এই তৈরি করা কাজ দেখতে পারে সবাই ! + +এটি দেখতে মোটামুটি এমনঃ + +![ফিগার ০.১ ](images/application.png) + +> তুমি যদি এই টিউটোরিয়াল নিজে নিজে কাজ করো এবং তোমার যদি কোচ না থাকে যে তোমাকে কোন সমস্যা পড়লে তোমাকে সাহায্য করবে । এই সমস্যা থেকে উত্তরণের জন্য আছে আমাদের চ্যাট সিস্টেম । আমরা আমাদের সকল কোচ এবং পূর্বে যারা এই টিউটোরিয়াল শেষ করেছে, তারা সেখানে থাকবে বিভিন্ন বিষয়ে সাহায্য করার জন্য। সেখানে প্রশ্ন করতে সংকোচবোধ করো না । + +ঠিক আছে,[ তাহলে শুরু করি ](./how_the_internet_works/README.md) + +## বাড়িতে বসে এই টিউটোরিয়াল অনুসরণ + +জাঙ্গো গার্লস ওয়ার্কশপে অংশ নেওয়া ভাল , তবে আমরা সচেতন যে সবসময় এটিতে অংশ নেওয়া সম্ভব নয়। এজন্যই আমরা তোমাদেরকে বাসায় বসে এই টিউটোরিয়াল অনুসরণ করার তাগিদ দিচ্ছি । যারা বাসায় বসে পড়বে, তাদের জন্য আমরা এখন ভিডিও তৈরি করছি যাতে এই টিউটোরিয়াল অনুসরণ করতে আরো সহজ হবে । এটির কাজ এখনো চলছে, তবে শীঘ্রই এই সকল বিষয় কাভার করা হবে ইউটিউবের এই চ্যানেলেঃ [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) + +প্রতিটি চ্যাপ্টার অলরেডি কভার হয়েছে এবং এর ভিডিওগুলো তোমরা লিংকে ক্লিক করলেই পেয়ে যাবে । + +## আমাদের সম্পর্কে এবং যাদের অবদান + +এই টিউটোরিয়ালটি মেইন্টেইন করে [জ্যাঙ্গোগার্লস](https://djangogirls.org/) তুমি যদি এই টিউটোরিয়ালে কোন ভুল বা কোন নতুন জিনিস যুক্ত করতে চাও তাহলে দয়া করে [এই লিংকে যাও](https://github.com/DjangoGirls/tutorial/blob/master/README.md) + +## তুমি কি আমাদের এই টিউটোরিয়ালটি অন্য ভাষায় ট্রান্সলেট করে অবদান রাখতে চাও? + +এখন, ট্রান্সলেশনের কাজটি crowdin.com প্লাটফর্মে রাখা আছে । + +https://crowdin.com/project/django-girls-tutorial + +যদি তোমার ভাষাটি [crowdin](https://crowdin.com/) এ না থাকে, দয়া করে [ একটি নতুন ইস্যু ](https://github.com/DjangoGirls/tutorial/issues/new) আমাদেরকে এই সম্পর্কে জানাও যাতে আমরা এটিকে যুক্ত করতে পারি । \ No newline at end of file diff --git a/bn-BD/SUMMARY.md b/bn-BD/SUMMARY.md new file mode 100644 index 00000000000..a4afb15cdd6 --- /dev/null +++ b/bn-BD/SUMMARY.md @@ -0,0 +1,35 @@ +# সারসংক্ষেপ + +* [ভূমিকা](README.md) +* [ইনস্টলেশন / স্থাপন](installation/README.md) + * [কমান্ড লাইন](installation/README.md#command-line) + * [পাইথন](installation/README.md#python) + * [কোড সম্পাদনকারী](installation/README.md#code-editor) + * [ভার্চুয়াল পরিবেশ](installation/README.md#virtualenv) + * [জ্যাঙ্গো](installation/README.md#django) + * [গিট](installation/README.md#git) + * [গিটহাব](installation/README.md#github-account) + * [পাইথনসবখানে](installation/README.md#pythonanywhere-account) +* [স্থাপন (ক্রোমবুক)](chromebook_setup/README.md) +* [ইন্টারনেট কিভাবে কাজ করে](how_the_internet_works/README.md) +* [কমান্ড লাইনের পরিচয়](intro_to_command_line/README.md) +* [পাইথন স্থাপনা](python_installation/README.md) +* [কোড এডিটর](code_editor/README.md) +* [পাইথন-এর পরিচিতি](python_introduction/README.md) +* [জ্যাঙ্গো কি?](django/README.md) +* [জ্যাঙ্গো স্থাপনা](django_installation/README.md) +* [আপনার প্রথম জ্যাঙ্গো প্রজেক্ট!](django_start_project/README.md) +* [জ্যাঙ্গো models](django_models/README.md) +* [জ্যাঙ্গো admin](django_admin/README.md) +* [প্রয়োগ!](deploy/README.md) +* [জ্যাঙ্গো URLs](django_urls/README.md) +* [জ্যাঙ্গো views - সময় প্রণয়ন করার!](django_views/README.md) +* [HTML এর পরিচিতি](html/README.md) +* [জ্যাঙ্গো ORM (অনুসন্ধানের ঝাঁক)](django_orm/README.md) +* [প্রগতিশীল ডেটা templates -এর মধ্যে](dynamic_data_in_templates/README.md) +* [জ্যাঙ্গো templates](django_templates/README.md) +* [CSS - এটি সুন্দর করুন ](css/README.md) +* [template বর্ধণ ](template_extending/README.md) +* [আপনার এপ্লিকেশনটি বড় করুন ](extend_your_application/README.md) +* [জ্যাঙ্গো Forms](django_forms/README.md) +* [এরপর কি? ](whats_next/README.md) \ No newline at end of file diff --git a/bn-BD/chromebook_setup/README.md b/bn-BD/chromebook_setup/README.md new file mode 100644 index 00000000000..bb84bd8c198 --- /dev/null +++ b/bn-BD/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# ক্রোমবুক সেটআপ + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/bn-BD/chromebook_setup/instructions.md b/bn-BD/chromebook_setup/instructions.md new file mode 100644 index 00000000000..4463b1e840a --- /dev/null +++ b/bn-BD/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +আপনি [এই বিভাগটি বাদ দিয় যেতে](http://tutorial.djangogirls.org/en/installation/#install-python) পারেন যদি আপনি ক্রোমবুক ব্যবহার না করে থাকেন। আর যদি আপনি করতে চান, তবে আপনা ক্রোমবুক স্থাপনের প্রক্রিয়াটির অভিজ্ঞনা একটু ভিন্ন হয়ে পারে। আপনি চাইলে বাকি স্থাপন নির্দেশনাবলী এড়িয়ে যেতে পারেন। + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +ক্লাউড আইডিই হচ্ছে এমন একটি টুল যটি আপনাকে ইন্টারনেটে কোড এডিটর এবং একটি কমিউটারের এক্সেস দিবে যেখানে আপনি সফটওয়্য্যার স্থাপন (install) , লিখতে ও পরিচালনা করতে পারবেন। টিউটোরিয়ালের সময় জুড়ে, ক্লাউড আইডিই আপনার *লোকাল মেশিন* এর মত ভূমিক পালন করবে। 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 IDE sets up for you. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). You can choose one of the cloud IDEs, and follow the instruction of the cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Go to [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Sign up for an account +3. Click *New Server* and choose the Django app +4. Click Terminal button(on the left side of the window) + +Now you should see an interface with a sidebar, buttons at the left. Click "Terminal" button to open terminal window with prompt like this: + +{% filename %}Terminal{% endfilename %} + + $ + + +The terminal on the PaizaCloud Cloud IDE is prepared for your instructions. You can resize or maximize that window to make it a bit bigger. + +#### AWS Cloud9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + yourusername:~/workspace $ + + +This bottom area is your terminal. You can use the terminal to send instructions to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### ভার্চুয়াল পরিবেশ + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(note that on the last line we use a tilde followed by an equal sign: `~=`). + +### গিটহাব + +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 for 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). \ No newline at end of file diff --git a/bn-BD/code_editor/README.md b/bn-BD/code_editor/README.md new file mode 100644 index 00000000000..82fdfaf0e9f --- /dev/null +++ b/bn-BD/code_editor/README.md @@ -0,0 +1,11 @@ +# কোড এডিটর + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +যেহেতু আপনি কোড লিখতে যাচ্ছেন তাই আপনার কোড এডিটর দরকার যেটা ডাউনলোড করার সময় এখনই! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. The cloud IDE you chose (PaizaCloud Cloud IDE or AWS Cloud9) includes a code editor, and when you open a file in your IDE from the File menu, you will automatically be using the editor. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/bn-BD/code_editor/instructions.md b/bn-BD/code_editor/instructions.md new file mode 100644 index 00000000000..dd7c73b883d --- /dev/null +++ b/bn-BD/code_editor/instructions.md @@ -0,0 +1,37 @@ +অনেক ধরণের কোড এডিটর পাওয়া যায় এবং আপনি কোনটা ব্যবহার করবেন সেটা নির্ভর করে পুরোপুরি আপনার উপর। সাধারণত পাইথন প্রোগ্রামাররা জটিল কিন্তু অনেক পাওয়ারফুল IDE (Integrated Development Environment) ব্যবহার করে থাকেন, যেমন পাইচার্ম। কিন্তু নতুনদের জন্য আমরা যেসব কোড এডিটর ব্যবহার করার পরামর্শ দেব সেগুলো একটু কম সুবিধাজনক হলেও সমান ক্ষমতাসম্পন্ন ও ব্যবহার করা অনেক সহজ। + +Our suggestions are below, but feel free to ask your coach what their preferences are – it'll be easier to get help from them. + +## Visual Studio Code + +Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + +[ডাউনলোড করতে এখানে ক্লিক করুন](https://code.visualstudio.com/) + +## Gedit + +Gedit is an open-source, free editor, available for all operating systems. + +[এখান থেকে ডাউনলোড করুন](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[এখান থেকে ডাউনলোড করুন](https://www.sublimetext.com/3) + +## Atom + +Atom is another popular editor. It's free, open-source and available for Windows, OS X and Linux. Atom is developed by [GitHub](https://github.com/). + +[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. + +তার প্রথম কারন হলো কোড **সাধারন টেক্সট** কিন্তু ওয়ার্ড বা টেক্সটএডিট- ধরনের সফ্টওয়্যারগুলো সাধারন টেক্সট তৈরী না করে রিচ টেক্সট(Rich Text) তৈরী করে যেটা RTF(Rich Text Format) বা এই ধরনের কোন ফর্মাটে থাকে।

+ +দ্বিতীয় কারন হলো কোডএডিটরের বিশেষ পারদর্শীতা হলো কোড এডিটিং, যাতে অনেক প্রয়োজনীয় জিনিস যেমন কোডকে তার বৈশিষ্ঠ্য অনুযায়ী রঙিন ভাবে দেখানো এবং বন্ধনীর(braces) কে নিজে থেকে শেষ করা ইত্যাদি। + +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. :) \ No newline at end of file diff --git a/bn-BD/css/README.md b/bn-BD/css/README.md new file mode 100644 index 00000000000..9b47bd8c274 --- /dev/null +++ b/bn-BD/css/README.md @@ -0,0 +1,330 @@ +# CSS - এটি সুন্দর করুন + +আমাদের ব্লগ তেমন সুন্দর দেখা যাচ্ছে না, তাই না? এখনি সুন্দর করার সময়! আমরা এইজন্য CSS ব্যাবহার করব। + +## CSS কি? + +CSS এর পূর্ণরুপ হচ্ছে Cascading Style Sheets এবং এটি একধরনের মার্কঅাপ ল্যাঙ্গুয়েজ(যেমন: HTML). যেটি ব্যবহার করা হয় ওয়েবসাইটের সৌন্দর্য্য এবং বিন্যাসের জন্য . এটিকে ওয়েবপেইজের সৌন্দয্য বলে ও ধরা হয় ;) . + +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: https://getbootstrap.com/ + +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, open up your `.html` file in the code editor and add this to the `` section: + +{% 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. So go ahead, open your website and refresh the page. Here it is! + +![Figure 14.1](images/bootstrap1.png) + +OK, save the file and refresh the site! + +## 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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +Django already knows where to find the static files for the built-in "admin" app. Now we 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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +But let's do at least a little. Maybe we could change the color of our headers? 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, h2 a { + color: #C25100; +} + +``` + +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element; the `h2 a` selector does the same thing for `h2` elements. 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 `#C25100`, which is a dark orange. Or you can put your own color here, but make sure it has good contrast against a white background! + +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 element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file in the code editor and add this line at the very beginning of it: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +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 be overriden by 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 static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/bn-BD/deploy/README.md b/bn-BD/deploy/README.md new file mode 100644 index 00000000000..00bc9abc351 --- /dev/null +++ b/bn-BD/deploy/README.md @@ -0,0 +1,246 @@ +# স্থাপন! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# গিট + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "আপনার নাম" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/bn-BD/deploy/install_git.md b/bn-BD/deploy/install_git.md new file mode 100644 index 00000000000..53fbe28d617 --- /dev/null +++ b/bn-BD/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in word processor programs (e.g., Microsoft Word or LibreOffice Writer), but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for two: in the step where it asks to choose your editor, you should pick Nano, and in the step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/bn-BD/deploy/signup_pythonanywhere.md b/bn-BD/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..555e36731dd --- /dev/null +++ b/bn-BD/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use it for hosting our site, live and on the Internet. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/bn-BD/django/README.md b/bn-BD/django/README.md new file mode 100644 index 00000000000..f72f5f12bd8 --- /dev/null +++ b/bn-BD/django/README.md @@ -0,0 +1,27 @@ +# Django কি? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. ওয়েব ফ্রেমওয়ার্ক হল উপকরনের সমষ্টি যা অাপনাকে দ্রুত ও সহজে ওয়েবসাইট বানাতে সাহায্য করে।. + +ওয়েবসাইট বানাতে হলে অামাদের সবসময়ই একই টাইপের উপকরন প্রয়োজন হয় । যেমন সাইন অাপ, সাইন ইন, ওয়েব সাইটের জন্য ম্যানেজমেন্ট প্যানেল, ফর্ম, ফাইল অাপলোডের জন্য ব্যাবস্থা করা ইত্যাদি। + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## ফ্রেমওয়ার্ক কেন প্রয়োজন? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +মনে কর একটা মেইলবক্স (পোর্ট) যেটার উপর প্রেরিত চিঠির(রিকুয়েস্ট) জন্য মনিটর করা হয়। এই সার্ভার একই কাজ করে। The web server reads the letter and then sends a response with a webpage. কিন্তু তুমি কিছু পাঠাতে চাইলে তোমার নকটেন্ট লাগবে। অার জ্যাঙ্গো হল সেটা যা তোমাকে কনটেন্ট তৈরিতে সাহাযা করবে। + +## কেউ তোমার সার্ভার থেকে রিকুয়েস্ট পাঠালে কি ঘটবে? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +চিঠিসহ একজন পত্রবাহককে কল্পনা কর। সে রাস্তা দিয়ে হাটছে অার চিঠির নাম্বারের সাথে বাড়ীর নাম্বার মিলিয়ে দেখছে। যদি এটা মিলে যায় তবে সে চিঠি রেখে অাসছে। একই ভাবে ইউঅার এল সার্ভার কাজ করে। + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. অাবার ইউজার ডাটাতে কোন পরিবর্তনের জন্য অনুরোধ করতে পারে। Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/bn-BD/django_admin/README.md b/bn-BD/django_admin/README.md new file mode 100644 index 00000000000..164d44e398e --- /dev/null +++ b/bn-BD/django_admin/README.md @@ -0,0 +1,57 @@ +# জ্যাঙ্গো এডমিন ( Django admin) + +আমরা জ্যাঙ্গো এডমিন ব্যবহার করে মডেলকৃত পোষ্ট যোগ , সংযুক্ত বা সম্পাদন এবং ডিলিট করতে পারবো। + +চলুন, তাহলে আমরা কোড এডিটরে `blog/admin.py` ফাইলটি ওপেন করি এবং ফাইলের বিষয়বস্তু পরিবর্তন করি । + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +আগের চ্যাপ্টারে যে পোষ্ট মডেলটি (Post model ) সংজ্ঞায়িত করেছিলাম সেটি এখানে আমরা ইম্পোর্ট(যুক্ত) করেছি। এডমিন প্যানেলে যাতে আমরা আমাদের মডেল দেখতে পারি সেইজন্য আমাদেরকে এইভাবে `admin.site.register(Post)` নিবন্ধন করতে হবে । + +চলুন, এখন তাহলে আমাদের পোষ্ট মডেলটি খেয়াল করে দেখি । মনে রাখতে হবে , ওয়েব সার্ভার রান করার জন্য কনসোলে(console ) এই `python manage.py runserver` কমান্ডটি দিতে হবে । এখন ব্রাউজারটি ওপেন করে http://127.0.0.1:8000/admin/ এই এড্রেসটি টাইপ করবো। তাহলে, আমরা একটি লগইন পেইজ এভাবে দেখবো : + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/bn-BD/django_forms/README.md b/bn-BD/django_forms/README.md new file mode 100644 index 00000000000..622df8798c1 --- /dev/null +++ b/bn-BD/django_forms/README.md @@ -0,0 +1,479 @@ +# জ্যাঙ্গো ফর্ম + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Security + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/bn-BD/django_installation/README.md b/bn-BD/django_installation/README.md new file mode 100644 index 00000000000..421af3ff2de --- /dev/null +++ b/bn-BD/django_installation/README.md @@ -0,0 +1,7 @@ +# Django সংস্থাপন + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/bn-BD/django_installation/instructions.md b/bn-BD/django_installation/instructions.md new file mode 100644 index 00000000000..fc965146844 --- /dev/null +++ b/bn-BD/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/bn-BD/django_models/README.md b/bn-BD/django_models/README.md new file mode 100644 index 00000000000..bcd473c08ea --- /dev/null +++ b/bn-BD/django_models/README.md @@ -0,0 +1,201 @@ +# Django মডেল + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/bn-BD/django_orm/README.md b/bn-BD/django_orm/README.md new file mode 100644 index 00000000000..ffe309bd81e --- /dev/null +++ b/bn-BD/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/bn-BD/django_start_project/README.md b/bn-BD/django_start_project/README.md new file mode 100644 index 00000000000..3767c62e17f --- /dev/null +++ b/bn-BD/django_start_project/README.md @@ -0,0 +1,260 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/bn-BD/django_templates/README.md b/bn-BD/django_templates/README.md new file mode 100644 index 00000000000..db2d20c4d4e --- /dev/null +++ b/bn-BD/django_templates/README.md @@ -0,0 +1,108 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/bn-BD/django_urls/README.md b/bn-BD/django_urls/README.md new file mode 100644 index 00000000000..d37a5e3c2fd --- /dev/null +++ b/bn-BD/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/bn-BD/django_views/README.md b/bn-BD/django_views/README.md new file mode 100644 index 00000000000..ab271e0914f --- /dev/null +++ b/bn-BD/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/bn-BD/dynamic_data_in_templates/README.md b/bn-BD/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..5a6ef017adf --- /dev/null +++ b/bn-BD/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/bn-BD/extend_your_application/README.md b/bn-BD/extend_your_application/README.md new file mode 100644 index 00000000000..c70a2db97ff --- /dev/null +++ b/bn-BD/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/bn-BD/how_the_internet_works/README.md b/bn-BD/how_the_internet_works/README.md new file mode 100644 index 00000000000..7b2c014c292 --- /dev/null +++ b/bn-BD/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![Figure 1.2](images/internet_3.png) + +It is fascinating, isn't it? But 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - you send messages and you expect some response. 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 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, 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 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! \ No newline at end of file diff --git a/bn-BD/html/README.md b/bn-BD/html/README.md new file mode 100644 index 00000000000..27c81ea68be --- /dev/null +++ b/bn-BD/html/README.md @@ -0,0 +1,227 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is 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 `TemplateDoesNotExist`, try to restart your server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +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 line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to GitHub + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% 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. + +{% 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: + +{% 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 %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/bn-BD/installation/README.md b/bn-BD/installation/README.md new file mode 100644 index 00000000000..b97592acbe8 --- /dev/null +++ b/bn-BD/installation/README.md @@ -0,0 +1,68 @@ +# 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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. + +Good luck! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Installation + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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. \ No newline at end of file diff --git a/bn-BD/intro_to_command_line/README.md b/bn-BD/intro_to_command_line/README.md new file mode 100644 index 00000000000..8a83f910ec6 --- /dev/null +++ b/bn-BD/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Your first command (YAY!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, huh? :) + +## সারাংশ + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/bn-BD/intro_to_command_line/open_instructions.md b/bn-BD/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/bn-BD/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/bn-BD/python_installation/README.md b/bn-BD/python_installation/README.md new file mode 100644 index 00000000000..8470b71f1f4 --- /dev/null +++ b/bn-BD/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/bn-BD/python_installation/instructions.md b/bn-BD/python_installation/instructions.md new file mode 100644 index 00000000000..592aafe0b5d --- /dev/null +++ b/bn-BD/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 the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/bn-BD/python_introduction/README.md b/bn-BD/python_introduction/README.md new file mode 100644 index 00000000000..ecafd5e6058 --- /dev/null +++ b/bn-BD/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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. + +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### সারাংশ + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 learned another amazing thing. + +### সারাংশ + +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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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, type the `exit()` function + +{% 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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### সারাংশ + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 by that we mean it includes the first value, but not the last. + +## সারাংশ + +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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/bn-BD/template_extending/README.md b/bn-BD/template_extending/README.md new file mode 100644 index 00000000000..d1c6d29d98e --- /dev/null +++ b/bn-BD/template_extending/README.md @@ -0,0 +1,151 @@ +# Template বর্ধন + +আপনার জন্য জাঙ্গো-এর আরেকটি আকর্ষণ হচ্ছে **template বর্ধন**। এর মানে কি? এর মানে হল আপনি আপনার ওয়েবসাইটে একই HML-এর অংশ ভিন্ন ভিন্ন ওয়েবপেজে ব্যবহার করতে পারবেন। + +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 a base template + +বেস টেমপ্লেট হল বেসিক টেমপ্লেট যা আপনি আপনার ওয়েবসাইটের প্রতিটি পৃষ্ঠায় বর্ধিত করে ব্যবহার করেন। + +এবার চলুন `blog/templates/blog/` এর ভিতরে `base.html` নামে একটি ফাইল তৈরি করি। + + blog + └───templates + └───blog + base.html + post_list.html + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +তারপর `base.html` `` এবং `` এর ভিতরে সব পরিবর্তন করি এটির সাথেঃ + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). আমরা এখন দেখব এটি কীভাবে কাজ করে। + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. এভাবে:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/bn-BD/whats_next/README.md b/bn-BD/whats_next/README.md new file mode 100644 index 00000000000..3795850d941 --- /dev/null +++ b/bn-BD/whats_next/README.md @@ -0,0 +1,43 @@ +# এরপর কি? + +নিজেকে অভিনন্দন দিন! **আপনি অসাধারণ **। আমরা গর্বিত! <3 + +### এখন কি করা যায়? + +বিরতি নিন এবং আরাম করুন! আপনি আসলেই ইতিমধ্যে অনেক কিছু করে ফেলেছেন। + +তদন্তর, আপ টু ডেট থাকার জন্য নিশ্চিত করুন আপনি জ্যাঙ্গো গার্লস এর [ফেসবুক](http://facebook.com/djangogirls) অথবা [টুইটার](https://twitter.com/djangogirls) একাউন্ট অনুসরণ করছেন। + +### আপনি কি আরও কোনো রিসোর্স সুপারিশ করতে পারেন? + +হ্যাঁ! অনলাইনে *অনেক * রিসোর্স আছে সকল প্রকার প্রোগ্রামিং স্কিল শেখার জন্য - এটা বেস ভয়ংকর কাজ যে একটা শেখার পর আরেকটা শিখতে কোথায় যাব, কিন্তু আমরা আপনাকে সয়ংসম্পূর্ণ করব। যাই হোক, জ্যাঙ্গো গার্লস-এ আসার পূর্বে আপনার আগ্রহ কেমন ছিল, এবং টিউটোরিয়াল-এর মাধ্যমে যে আগ্রহই তৈরি করুন, এখানে কিছু ফ্রি রিসোর্স দেওয়া হল ( যে রিসোর্স অনেক উপাদানে সয়ংসম্পূর্ণ) আপনি এগুলো ব্যবহার করতে পারেন যেখানে চাইবেন। + +#### জ্যাঙ্গো + +- আমাদের অন্যান্য বই, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [জ্যাঙ্গো-এর অফিশিয়াল টিউটোরিয়াল](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [শুরু করুন জ্যাঙ্গো ভিডিও পাঠের মাধ্যমে](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS এবং JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### পাইথন + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) - প্রাথমিক অনুশীলনগুলো পাবেন একদম বিনামূল্যে +- [New Coder tutorials](http://newcoder.io/tutorials/) - এটি কিভাবে পাইথন প্রয়োগ করতে পারেন তার বৈচিত্রপূর্ণ ব্যবহারিক উদাহরণসমূহ +- [edX](https://www.edx.org/course?search_query=python) - আপনি এখান থেকে বেশিভাগ কোর্সই বিনামূল্যে পেতে পারেন, কিন্তু আপনি যদি উচ্চ শিক্ষার যোগ্যতার সনদ বা ক্রেডিট নিতে চান তাহলে আপনাকে টাকা প্রদান করতে হবে +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) - কিছু ভিডিও লেকচার বিনামূল্যে পেতে পারেন এবং আপনি কোর্সগুলোর জন্য Coursera-থেকে সনদও নিতে পারবেন । +- পাইথন সবার জন্য ([Python for Everybody](https://www.py4e.com/)) - সবাইকে পাইথন-এ দক্ষ করার জন্য Coursera- এর পক্ষ থেকে একটি ফ্রি ও উন্মুক্ত কোর্স। + +#### ডেটা নিয়ে যত কাজ + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) - আপনি এখান থেকে বেশিভাগ কোর্সই বিনামূল্যে পেতে পারেন, কিন্তু আপনি যদি উচ্চ শিক্ষার যোগ্যতার সনদ বা ক্রেডিট নিতে চান তাহলে আপনাকে টাকা প্রদান করতে হবে +- [Dataquest](https://www.dataquest.io/) - প্রথম ৩০ "missions" একদম বিনামূল্যে + +আপনি পরবর্তীতে কি তৈরি করছেন সেটা দেখার জন্য আমরা আর অপেক্ষা করতে পারছিনা! \ No newline at end of file diff --git a/bn/GLOSSARY.md b/bn/GLOSSARY.md new file mode 100644 index 00000000000..2e928dda548 --- /dev/null +++ b/bn/GLOSSARY.md @@ -0,0 +1,3 @@ +# code editor + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/bn/README.md b/bn/README.md new file mode 100644 index 00000000000..a402ff95c48 --- /dev/null +++ b/bn/README.md @@ -0,0 +1,51 @@ +# Django মেয়েরা টিউটোরিয়াল + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) + +## ভূমিকা + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? আপনি কি ওয়েবসাইট বানানো শিখতে চান, কিন্তু বিভিন্ন কারনে পারছেন না? বর্তমান সফটওয়্যার শিল্প কি আপনার নিজের সামান্য কোনো সফটওয়্যার বানানোর জন্যও অনেক জটিল মনে হয়? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/bn/SUMMARY.md b/bn/SUMMARY.md new file mode 100644 index 00000000000..65e95596268 --- /dev/null +++ b/bn/SUMMARY.md @@ -0,0 +1,27 @@ +# সারাংশ + +* [ভূমিকা](README.md) +* [Installation](installation/README.md) +* [Installation (chromebook)](chromebook_setup/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/README.md) +* [Introduction to Python](python_introduction/README.md) +* [Django কি?](django/README.md) +* [Django সংস্থাপন](django_installation/README.md) +* [Your first Django project!](django_start_project/README.md) +* [Django মডেল](django_models/README.md) +* [Django admin](django_admin/README.md) +* [স্থাপন!](deploy/README.md) +* [Django urls](django_urls/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) +* [টেম্পলেট বর্ধন](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [জ্যাঙ্গো ফর্ম](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/bn/chromebook_setup/README.md b/bn/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/bn/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/bn/chromebook_setup/instructions.md b/bn/chromebook_setup/instructions.md new file mode 100644 index 00000000000..809281456d3 --- /dev/null +++ b/bn/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/bn/code_editor/README.md b/bn/code_editor/README.md new file mode 100644 index 00000000000..fb33bbdb9be --- /dev/null +++ b/bn/code_editor/README.md @@ -0,0 +1,11 @@ +# কোড এডিটর + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +যেহেতু আপনি কোড লিখতে যাচ্ছেন তাই আপনার কোড এডিটর দরকার যেটা ডাউনলোড করার সময় এখনই! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/bn/code_editor/instructions.md b/bn/code_editor/instructions.md new file mode 100644 index 00000000000..8c4542de99e --- /dev/null +++ b/bn/code_editor/instructions.md @@ -0,0 +1,31 @@ +অনেক ধরণের কোড এডিটর পাওয়া যায় এবং আপনি কোনটা ব্যবহার করবেন সেটা নির্ভর করে পুরোপুরি আপনার উপর। সাধারণত পাইথন প্রোগ্রামাররা জটিল কিন্তু অনেক পাওয়ারফুল IDE (Integrated Development Environment) ব্যবহার করে থাকেন, যেমন পাইচার্ম। কিন্তু নতুনদের জন্য আমরা যেসব কোড এডিটর ব্যবহার করার পরামর্শ দেব সেগুলো একটু কম সুবিধাজনক হলেও সমান ক্ষমতাসম্পন্ন ও ব্যবহার করা অনেক সহজ। + +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 ওপেন সোর্স ও ফ্রি এডিটর এবং সকল অপারেটিং সিস্টেম সাপোর্ট করে (যেমন লিনাক্স, উইন্ডোজ ইত্যাদি)। + +[ডাউনলোড করতে এখানে ক্লিক করুন](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[এখান থেকে ডাউনলোড করুন](https://www.sublimetext.com/3) + +## Atom + +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. + +[এখান থেকে ডাউনলোড করুন](https://atom.io/) + +## আমরা কেন কোড এডিটর ইন্সটল করব? + +আপনি হয়ত অবাক হচ্ছেন কেন আমরা কোড এডিটর নামে বিশেষ সফটওয়্যার ইন্সটল করছি , সাধারন ওয়ার্ড বা নোটপ্যাড ব্যবহার না করে। + +তার প্রথম কারন হলো কোড **সাধারন টেক্সট** কিন্তু ওয়ার্ড বা টেক্সটএডিট- ধরনের সফ্টওয়্যারগুলো সাধারন টেক্সট তৈরী না করে রিচ টেক্সট(Rich Text) তৈরী করে যেটা RTF(Rich Text Format) বা এই ধরনের কোন ফর্মাটে থাকে।

+ +দ্বিতীয় কারন হলো কোডএডিটরের বিশেষ পারদর্শীতা হলো কোড এডিটিং, যাতে অনেক প্রয়োজনীয় জিনিস যেমন কোডকে তার বৈশিষ্ঠ্য অনুযায়ী রঙিন ভাবে দেখানো এবং বন্ধনীর(braces) কে নিজে থেকে শেষ করা ইত্যাদি। + +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. :) \ No newline at end of file diff --git a/bn/css/README.md b/bn/css/README.md new file mode 100644 index 00000000000..6e04ae8507c --- /dev/null +++ b/bn/css/README.md @@ -0,0 +1,304 @@ +# CSS – make it pretty! + +আমাদের ব্লগ তেমন সুন্দর দেখা যাচ্ছে না, তাই না? এখনি সুন্দর করার সময়! আমরা এইজন্য CSS ব্যাবহার করব। + +## CSS কি? + +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? 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: https://getbootstrap.com/ + +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: + +{% 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! + +![Figure 14.1](images/bootstrap1.png) + +OK, save the file and refresh the site! + +## 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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +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. 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 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 + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +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. :) 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 be overriden by 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 %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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 + +``` + +And now add a class `post` to your `div` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/bn/deploy/README.md b/bn/deploy/README.md new file mode 100644 index 00000000000..c2b032bb740 --- /dev/null +++ b/bn/deploy/README.md @@ -0,0 +1,260 @@ +# স্থাপন! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ 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) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. + +Hit **Save** and then go back to the **Web** tab. + +We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. + +## Debugging tips + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: + +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. + +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. + +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? + +- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. + +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +And remember, your coach is here to help! + +# You are live! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! \ No newline at end of file diff --git a/bn/deploy/install_git.md b/bn/deploy/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/bn/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/bn/deploy/signup_pythonanywhere.md b/bn/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/bn/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/bn/django/README.md b/bn/django/README.md new file mode 100644 index 00000000000..6a17a644184 --- /dev/null +++ b/bn/django/README.md @@ -0,0 +1,27 @@ +# Django কি? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. ওয়েব ফ্রেমওয়ার্ক হল উপকরনের সমষ্টি যা অাপনাকে দ্রুত ও সহজে ওয়েবসাইট বানাতে সাহায্য করে।. + +ওয়েবসাইট বানাতে হলে অামাদের সবসময়ই একই টাইপের উপকরন প্রয়োজন হয় । যেমন সাইন অাপ, সাইন ইন, ওয়েব সাইটের জন্য ম্যানেজমেন্ট প্যানেল, ফর্ম, ফাইল অাপলোডের জন্য ব্যাবস্থা করা ইত্যাদি। + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## ফ্রেমওয়ার্ক কেন প্রয়োজন? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +মনে কর একটা মেইলবক্স (পোর্ট) যেটার উপর প্রেরিত চিঠির(রিকুয়েস্ট) জন্য মনিটর করা হয়। এই সার্ভার একই কাজ করে। The web server reads the letter and then sends a response with a webpage. কিন্তু তুমি কিছু পাঠাতে চাইলে তোমার নকটেন্ট লাগবে। অার জ্যাঙ্গো হল সেটা যা তোমাকে কনটেন্ট তৈরিতে সাহাযা করবে। + +## কেউ তোমার সার্ভার থেকে রিকুয়েস্ট পাঠালে কি ঘটবে? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +চিঠিসহ একজন পত্রবাহককে কল্পনা কর। সে রাস্তা দিয়ে হাটছে অার চিঠির নাম্বারের সাথে বাড়ীর নাম্বার মিলিয়ে দেখছে। যদি এটা মিলে যায় তবে সে চিঠি রেখে অাসছে। একই ভাবে ইউঅার এল সার্ভার কাজ করে। + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. অাবার ইউজার ডাটাতে কোন পরিবর্তনের জন্য অনুরোধ করতে পারে। Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +তারপর <0>view রিকুয়েস্ট তৈরি করে অার জ্যাঙ্গো সেটাকে ইউজারের ওয়েব ব্রাউজারের পাঠাতে পারে। + +অামার অার গভীরে না গিয়ে জ্যাঙ্গো দিয়ে সহজ কিছু তৈরি করব অার এভাবেই অামরা গুরুত্বপুর্ন অংশ গুলো শিখে ফেলব। \ No newline at end of file diff --git a/bn/django_admin/README.md b/bn/django_admin/README.md new file mode 100644 index 00000000000..46a5afbb500 --- /dev/null +++ b/bn/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/bn/django_forms/README.md b/bn/django_forms/README.md new file mode 100644 index 00000000000..6523c130238 --- /dev/null +++ b/bn/django_forms/README.md @@ -0,0 +1,447 @@ +# জ্যাঙ্গো ফর্ম + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? + +## URL + +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```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` we add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## Security + +Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to Github: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/bn/django_installation/README.md b/bn/django_installation/README.md new file mode 100644 index 00000000000..38eb16f0918 --- /dev/null +++ b/bn/django_installation/README.md @@ -0,0 +1,7 @@ +# Django সংস্থাপন + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/bn/django_installation/instructions.md b/bn/django_installation/instructions.md new file mode 100644 index 00000000000..0bc080f7055 --- /dev/null +++ b/bn/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/bn/django_models/README.md b/bn/django_models/README.md new file mode 100644 index 00000000000..c367f4dbab6 --- /dev/null +++ b/bn/django_models/README.md @@ -0,0 +1,199 @@ +# Django মডেল + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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 + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/bn/django_orm/README.md b/bn/django_orm/README.md new file mode 100644 index 00000000000..31c47f27764 --- /dev/null +++ b/bn/django_orm/README.md @@ -0,0 +1,218 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Chaining QuerySets + +You can also combine QuerySets by **chaining** them together: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/bn/django_start_project/README.md b/bn/django_start_project/README.md new file mode 100644 index 00000000000..fe1abc7ca9a --- /dev/null +++ b/bn/django_start_project/README.md @@ -0,0 +1,202 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![It worked!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/bn/django_templates/README.md b/bn/django_templates/README.md new file mode 100644 index 00000000000..263eb1fd835 --- /dev/null +++ b/bn/django_templates/README.md @@ -0,0 +1,106 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/bn/django_urls/README.md b/bn/django_urls/README.md new file mode 100644 index 00000000000..c491b27de5c --- /dev/null +++ b/bn/django_urls/README.md @@ -0,0 +1,129 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![Url](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Regex + +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. + +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: + +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern + +Anything else in the URL definition will be taken literally. + +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. + +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: + +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/bn/django_views/README.md b/bn/django_views/README.md new file mode 100644 index 00000000000..07afe091a52 --- /dev/null +++ b/bn/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/bn/dynamic_data_in_templates/README.md b/bn/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..807bb666ebc --- /dev/null +++ b/bn/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/bn/extend_your_application/README.md b/bn/extend_your_application/README.md new file mode 100644 index 00000000000..0bae760be7c --- /dev/null +++ b/bn/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: + +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? Of course: adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`. + +It will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ 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 %} + +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 --all . + $ git status + $ 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/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/bn/how_the_internet_works/README.md b/bn/how_the_internet_works/README.md new file mode 100644 index 00000000000..efd95c3f4b2 --- /dev/null +++ b/bn/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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. + +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![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 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - 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 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, 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 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! \ No newline at end of file diff --git a/bn/html/README.md b/bn/html/README.md new file mode 100644 index 00000000000..004985089c2 --- /dev/null +++ b/bn/html/README.md @@ -0,0 +1,213 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Add the following to your template file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +

Hi there!

+

It works!

+ +``` + +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 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `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, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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.

+
+ + +``` + +We've created three `div` sections here. + +* 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to Github + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% 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: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **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): + +{% 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. + +{% 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: + +{% 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 + $ git pull + [...] + + +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. + +* 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. :) \ No newline at end of file diff --git a/bn/install_git.md b/bn/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/bn/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/bn/installation/README.md b/bn/installation/README.md new file mode 100644 index 00000000000..ccdfcd6f042 --- /dev/null +++ b/bn/installation/README.md @@ -0,0 +1,58 @@ +# 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 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) + +* [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. \ No newline at end of file diff --git a/bn/instructions.md b/bn/instructions.md new file mode 100644 index 00000000000..30bd493b11b --- /dev/null +++ b/bn/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/bn/intro_to_command_line/README.md b/bn/intro_to_command_line/README.md new file mode 100644 index 00000000000..927cc65f7e5 --- /dev/null +++ b/bn/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +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. :) + +> 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 by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, huh? :) + +## সারাংশ + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/bn/python_installation/README.md b/bn/python_installation/README.md new file mode 100644 index 00000000000..93f81cb42d9 --- /dev/null +++ b/bn/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/bn/python_installation/instructions.md b/bn/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/bn/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/bn/python_introduction/README.md b/bn/python_introduction/README.md new file mode 100644 index 00000000000..d1252c4408a --- /dev/null +++ b/bn/python_introduction/README.md @@ -0,0 +1,1062 @@ +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.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. + +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. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, simply type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### সারাংশ + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% 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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% 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! + +{% 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% 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 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 learned another amazing thing. + +### সারাংশ + +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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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 + +{% 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!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### সারাংশ + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 by that we mean it includes the first value, but not the last. + +## সারাংশ + +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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/bn/signup_pythonanywhere.md b/bn/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/bn/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/bn/template_extending/README.md b/bn/template_extending/README.md new file mode 100644 index 00000000000..c6e50445eb4 --- /dev/null +++ b/bn/template_extending/README.md @@ -0,0 +1,147 @@ +# টেম্পলেট বর্ধন + +জাঙ্গোর আরেকটি সুন্দর বিষয় হচ্ছে **টেম্পলেট বর্ধন**। এর মানে কি? এর মানে হল আপনি আপনার ওয়েবসাইটে একই এইচটিএমএল এর অংশ ভিন্ন ভিন্ন ওয়েবপেজে ব্যবহার করতে পারবেন। + +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 a base template + +বেস টেমপ্লেট হল বেসিক টেমপ্লেট যা আপনি আপনার ওয়েবসাইটের প্রতিটি পৃষ্ঠায় বর্ধিত করে ব্যবহার করেন। + +এবার চলুন `blog/templates/blog/` এর ভিতরে `base.html` নামে একটি ফাইল তৈরি করি। + + blog + └───templates + └───blog + base.html + post_list.html + + +এটি ওপেন করার পর `post_list.html` থেকে সবকিছু `base.html` ফাইলে কপি করি, নিচের মত করেঃ + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +তারপর `base.html` `` এবং `` এর ভিতরে সব পরিবর্তন করি এটির সাথেঃ + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). আমরা এখন দেখব এটি কীভাবে কাজ করে। + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. এভাবে:{% 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' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +ব্যাস! চেক করুন আপনার ওয়েব সাইটের এখনো সঠিকভাবে কাজ করছে কিন. :) + +> 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. \ No newline at end of file diff --git a/bn/whats_next/README.md b/bn/whats_next/README.md new file mode 100644 index 00000000000..fbb1d2a7d6e --- /dev/null +++ b/bn/whats_next/README.md @@ -0,0 +1,25 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](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](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). + +Later on, you can try the resources listed below. They're all very recommended! + +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/ca-ES/GLOSSARY.md b/ca-ES/GLOSSARY.md new file mode 100644 index 00000000000..808f592bd33 --- /dev/null +++ b/ca-ES/GLOSSARY.md @@ -0,0 +1,3 @@ +# editor de codi + +L'editor de codi és una aplicació que et permet guardar el teu codi de manera que puguis tornar-hi més tard. Pots saber on aconseguir-ne un al [Capítol sobre l'editor de codi](./code_editor/README.md) \ No newline at end of file diff --git a/ca-ES/README.md b/ca-ES/README.md new file mode 100644 index 00000000000..acb370a8988 --- /dev/null +++ b/ca-ES/README.md @@ -0,0 +1,51 @@ +# Tutorial de les Django Girls + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> Aquest treball té una llicència Internacional Creative Commons de Reconeixement - Compartir Igual 4.0. Per a veure una còpia d'aquesta llicència, visita https://creativecommons.org/licenses/by-sa/4.0/ + +## Benvinguda + +Benvingudes al Tutorial Noies Django! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Introducció + +Alguna vegada has sentit que al món cada vegada hi ha més tecnologia que et resulta (de moment) estranya? Alguna vegada t'has preguntat com crear una pàgina web però t'ha faltat motivació per començar? Alguna vegada has pensat que el món del software és massa complicat com per ni tan sols provar-ho pel teu compte? + +Bé, tenim bones notícies! Programar no és pas tan difícil com sembla i et volem ensenyar com pot ser de divertit. + +Aquest tutorial no et convertirà en programador com per art de màgia. Per a fer-ho bé, cal mesos o anys de pràctica. Però et volem demostrar que programar o crear llocs web no és tan dicícil com sembla. Intentarem explicar diferents parts tan bé com poguem, perquè no et sentis intimidada per la tecnologia. + +Esperem ser capaços de transmetre't el nostre amor per la tecnologia! + +## Què aprendràs en aquest tutorial? + +Un cop hauràs acabat el tutorial, tindràs una petita web en funcionament: el teu propi blog. T'ensenyarem com posar-lo en línia, de manera que altra gent pugui veure la teva feina! + +Tindrà (més o menys) aquest aspecte: + +![Figura 0.1](images/application.png) + +> Si treballes amb el tutorial pel teu compte i no tens ajuda t'ajudarem en cas de problema, tenim un xat:[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). Hem demanat als nostres instructors i antics alumnes que vinguin per aquí de tan en tant per ajudar amb el tutorial! No tinguis por de preguntar! + +D'acord, [comencem perl principi...](./how_the_internet_works/README.md) + +## Seguint el tutorial des de casa + +És increïble participar a un taller de Noies Django, però som conscients que no sempre és fàcil assistir. Per això t'animem a seguir el tutorial des de casa. Per als que ens llegeixen des de casa, ara estem preparant vídeos que faran més fàcil seguir el tutorial pel vostre compte. És una feina que encara està en curs, però s'aniran cobrint cada vegada més continguts al canal de Youtube [Programar és cosa de noies](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed). + +A cada capítol ja cobert, hi ha un enllaç que dirigeix al vídeo corresponent. + +## Sobre nosaltres i Contribució + +Aquest tutorial és mantingut per [Noies Django](https://djangogirls.org/). Si trobes algun error o vols actualitzar el tutorial si us plau [segueix les guies de contribució](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## T'agradaria ajudar-nos a traduir el tutorial a altres llengües? + +En aquest moment, les traduccions es guarden a la plataforma crowdin.com a: + +https://crowdin.com/project/django-girls-tutorial + +Si la teva llengua no és a la llista a [crowdin](https://crowdin.com/), si us plau[obre un nou assumpte](https://github.com/DjangoGirls/tutorial/issues/new)informant-nos de la llengua que falta per a que la poguem afegir. \ No newline at end of file diff --git a/ca-ES/SUMMARY.md b/ca-ES/SUMMARY.md new file mode 100644 index 00000000000..401d2e90f12 --- /dev/null +++ b/ca-ES/SUMMARY.md @@ -0,0 +1,35 @@ +# Resum + +* [Introducció](README.md) +* [Instal·lació](installation/README.md) + * [Command Line](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Code Editor](installation/README.md#code-editor) + * [Virtual Environment](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Instal·lació (chromebook)](chromebook_setup/README.md) +* [Com funciona Internet](how_the_internet_works/README.md) +* [Introducció a línia d'ordres](intro_to_command_line/README.md) +* [Instal·lació de Python](python_installation/README.md) +* [Editor de codi](code_editor/README.md) +* [Introducció a Python](python_introduction/README.md) +* [Què és Django?](django/README.md) +* [Django installation](django_installation/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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/ca-ES/chromebook_setup/README.md b/ca-ES/chromebook_setup/README.md new file mode 100644 index 00000000000..c4a4c860b13 --- /dev/null +++ b/ca-ES/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Instal·lació en Chromebook + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/ca-ES/chromebook_setup/instructions.md b/ca-ES/chromebook_setup/instructions.md new file mode 100644 index 00000000000..b48dc92b80b --- /dev/null +++ b/ca-ES/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Pots [saltar fins aquesta secció](http://tutorial.djangogirls.org/en/installation/#install-python) si no fas servir un Chromebook. Si el fas servir, la teva experiència d'instal·lació serà una mica diferent. Pots ignorar la resta d'instruccions d'instal·lació. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +L'entorn de desenvolupament integrat (IDE) en núvol és una eina que t'ofereix un editor de codi i accés a un ordinador funcionant a Internet, on pots instal·lar, escriure i executar el programari. Durant la resta del tutorial, aquest IDE en núvol actuarà com la teva *màquina local*. Executaràs comandes des d'una interfície de terminal, com les teves companyes de classe fan amb OS X, Ubuntu o Windows, però la teva estarà conectada a un ordinador executant-se en algun altre lloc de la xarxa. El IDE en núvol la prepararà per a tu. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). Pots elegir-ne un i seguir les seves instruccions. + +#### PaizaCloud Cloud IDE + +1. Ves a [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Registra't +3. Click *New Server* and choose the Django app +4. Clica el botò Terminal (a la part esquerra de la finestra) + +Now you should see an interface with a sidebar, buttons at the left. Click "Terminal" button to open terminal window with prompt like this: + +{% filename %}Terminal{% endfilename %} + + $ + + +The terminal on the PaizaCloud Cloud IDE is prepared for your instructions. You can resize or maximize that window to make it a bit bigger. + +#### AWS Cloud9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + yourusername:~/workspace $ + + +This bottom area is your terminal. You can use the terminal to send instructions to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### Entorn Virtual + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/ca-ES/code_editor/README.md b/ca-ES/code_editor/README.md new file mode 100644 index 00000000000..ebbf0bef58d --- /dev/null +++ b/ca-ES/code_editor/README.md @@ -0,0 +1,11 @@ +# Editor de codi + +> Per les lectores que són a casa: el vídeo [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) tracta sobre aquest tema. + +En breu escriuràs la teva primera línia de codi, així que ha arribat l'hora de descarregar un editor de codi! + +> **Nota** Si estàs fent servir un Chromebook, salta't aquest capítol i segueix les instruccions que trobaràs a [Chromebook Setup](../chromebook_setup/README.md). L'IDE cloud que has triat (PaizaCloud Cloud IDE o AWS Cloud9) inclou un editor de codi. Així doncs, quan obris un fitxer al teu IDE des del menú d'arxiu ja estaràs emprant l'editor. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/ca-ES/code_editor/instructions.md b/ca-ES/code_editor/instructions.md new file mode 100644 index 00000000000..55d19377660 --- /dev/null +++ b/ca-ES/code_editor/instructions.md @@ -0,0 +1,37 @@ +Hi ha molts editors de codi diferents. L'elecció d'un o d'altre editor dependrà bàsicament de preferències personals. La majoria de programadores en Python van més enllà i utilitzen IDEs (entorns de desenvolupament integrat -Integrated Development Environments-) complexos però extremadament potents, com ara PyCharm. Aquesta darrera opció, però, és segurament poc adient per algú que tot just comença a programar. Les nostres recomanacions són igual de potents, però molt més simples. + +A continuació trobaràs les nostres recomanacions. Pots demanar a la teva instructora si té alguna preferència, així li serà més fàcil ajudar-te. + +## Visual Studio Code + +Visual Studio Code és un editor de codi desenvolupat per Microsoft per als sistemes Windows, Linux i macOS. Inclou suport per deupració, control de Git encastat, sintaxi reslatada, completació intel·ligent de codi, snippets i refactorització de codi. + +[Descarrega'l aquí](https://code.visualstudio.com/) + +## Gedit + +Gedit és un editor gratuit, de programari lliure, disponible per tots els sistemes operatius. + +[Descarrega'l aquí](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text és un editor molt popular amb un període d'avaluació gratuït i disponible per tots els sistemes operatius. + +[Descarrega'l aquí](https://www.sublimetext.com/3) + +## Atom + +Atom és un altre editor popular. És gratiut, de programari lliure i disponible per Windows, OS X i Linux. Atom és desenvolupat per [GitHub](https://github.com/). + +[Descarrega'l aquí](https://atom.io/) + +## Per què estem instal·lant un editor de codi? + +Et pots estar demanant per què estem instal·lant programari específic per codi, en lloc d'usar alternatives com Word o Notepad. + +La primera raó és que el codi s'ha d'emmagatzemar en **text pla**. El problema amb programes com el Word o el TextEdit és que, per defecte, no produeixen text pla. Produeixen text enriquit (amb fonts i format), utilitzant formats personalitzats com el [RTF (Format de Text Enriquit -Rich Text Format -)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +La segona raó és que els editors de codi s'han especialitzat precisament en això, en editar codi. Així doncs, proporcionen característiques útils com acolorir el text del codi en funció del seu significat o tancar-te automàticament els parèntesis. + +Més endavant veurem tot això a la pràctica. Aviat consideraràs el teu antic i fidel editor de codi com una de les teves eines favorites. :) \ No newline at end of file diff --git a/ca-ES/css/README.md b/ca-ES/css/README.md new file mode 100644 index 00000000000..f2f78b2317a --- /dev/null +++ b/ca-ES/css/README.md @@ -0,0 +1,330 @@ +# CSS - fes-lo maco! + +El nostre blog encara sembla una mica lleig, oi? És hora de fer-lo maco! Per a això farem servir els CSS. + +## Què són els CSS? + +Els fulls d’estil en cascada (Cascading Style Sheets -CSS-) es fan servir per definir com es formatarà i veurà un lloc web escrit en un llenguatge de marcat (com l'HTML). Els pots considerar com el maquillatge de la nostra pàgina web. ;) + +Però no volem tornar a començar des de zero, oi? Un cop més, farem servir una eina gratuïta distribuïda per Internet. Saps, reinventar la roda no és divertit. + +## Utilitzem Bootstrap! + +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. Now it's developed by volunteers from all over the world! + +## Install Bootstrap + +To install Bootstrap, open up your `.html` file in the code editor and add this to the `` section: + +{% 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. So go ahead, open your website and refresh the page. Here it is! + +![Figure 14.1](images/bootstrap1.png) + +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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +Django already knows where to find the static files for the built-in "admin" app. Now we 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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +But let's do at least a little. Maybe we could change the color of our headers? 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, h2 a { + color: #C25100; +} + +``` + +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element; the `h2 a` selector does the same thing for `h2` elements. 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 `#C25100`, which is a dark orange. Or you can put your own color here, but make sure it has good contrast against a white background! + +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 element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file in the code editor and add this line at the very beginning of it: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +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 be overriden by 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 static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/ca-ES/deploy/README.md b/ca-ES/deploy/README.md new file mode 100644 index 00000000000..cc2d165200c --- /dev/null +++ b/ca-ES/deploy/README.md @@ -0,0 +1,246 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/ca-ES/deploy/install_git.md b/ca-ES/deploy/install_git.md new file mode 100644 index 00000000000..53fbe28d617 --- /dev/null +++ b/ca-ES/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in word processor programs (e.g., Microsoft Word or LibreOffice Writer), but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for two: in the step where it asks to choose your editor, you should pick Nano, and in the step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/ca-ES/deploy/signup_pythonanywhere.md b/ca-ES/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..555e36731dd --- /dev/null +++ b/ca-ES/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use it for hosting our site, live and on the Internet. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/ca-ES/django/README.md b/ca-ES/django/README.md new file mode 100644 index 00000000000..f87d87954c4 --- /dev/null +++ b/ca-ES/django/README.md @@ -0,0 +1,27 @@ +# Què és Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) és un entorn de treball per aplicacions web (framework web) de codi lliure i gratuït escrit en Python. Un framework web consta d'un seguit de components que ens ajuda a desenvolupar llocs web d'una forma més fàcil i ràpida. + +En la construcció d'un lloc web necessitem sempre un conjunt de components semblant: una forma de gestionar l'autenticació d'usuaris (registre, inici i tancament de sessió), un panell de control, formularis, un sistema per carregar fitxers, etc. + +Afortunadament per nosaltres, algú es va adonar fa molt de temps que les desenvolupadores web s'enfronten un i altre cop als mateixos problemes quan construeixen un lloc web. Així doncs, es van unir i crearen frameworks (com ara Django) amb components llestos per ser emprats. + +Els frameworks existeixen per estalviar-nos haver de reinventar la roda i ajudar-nos a disminuir el treball addicional que això implica quan estem construint un nou lloc web. + +## Per què necessitem un framework? + +Per entendre la finalitat de Django necessitem entendre una mica els servidors. La primera cosa de la que un servidor se n'ha d'adonar és que volem que ens proporcioni una determinada pàgina web. + +Imagina una bústia de correu (port) que s'observa per saber quan arriben cartes (peticions). Això mateix és el que fa un servidor web. El servidor web llegeix la carta i envia una resposta amb la pàgina web. Per enviar alguna cosa, però, necessitem un contingut. Contingut que Django ens ajuda a crear. + +## Què és el que passa quan algú demana per un lloc web al teu servidor? + +Quan una petició arriba al servidor web, s'envia a Django, que tracta d'entendre que és el que se li està demanant. Primer agafa l'adreça de la pàgina web i intenta esbrinar què n'ha de fer. D'això s'encarrega un component de Django anomenat **urlresolver** (fixa't que l'adreça d'un lloc web es diu URL (localitzador uniforme de recursos – Uniform Resource Locator –. Per tant, el mot *urlresolver* sembla ben triat). Aquest component no és gaire llest: disposa d'un llistat de patrons i mira d'esbrinar a quin d'ells s'ajusta la URL en qüestió. Django revisa els patrons d'adalt a baix i si en troba un de coincident, aleshores envia la petició a la funció associada (que anomenem *view* – vista –). + +Imagina una cartera que ha d'entregar una carta. Va caminant pel carrer tot mirant els números dels edificis per trobar el que coincideix amb el que duu la carta. Si en troba un que coincideix, allà l'entrega. Així és com funciona l'urlresolver! + +A la funció *view* és on es fan les coses interessants: podem buscar informació en una base de dades. L'usuari potser demana que es canviï alguna dada? Com una carta que digui: "Si us plau, canvia la descripció de la meva feina." La *view* pot comprovar si s'està autoritzat a fer-ho i, si és el cas, actualitzar la descripció i enviar un missatge de confirmació: "Fet!" Aleshores la *view* genera una resposta i Django la pot enviar al navegador de l'usuari. + +L'anterior explicació s'ha simplificat una mica ja que encara no cal que sàpigues tots els detalls tècnics. Amb que tinguis una idea general ja n'hi ha prou. + +Així doncs, enlloc d'aprofundir massa en els detalls, començarem creant alguna cosa amb Django i així aprendrem com funcionen els components importants! \ No newline at end of file diff --git a/ca-ES/django_admin/README.md b/ca-ES/django_admin/README.md new file mode 100644 index 00000000000..156eae05654 --- /dev/null +++ b/ca-ES/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/ca-ES/django_forms/README.md b/ca-ES/django_forms/README.md new file mode 100644 index 00000000000..68676f99fa5 --- /dev/null +++ b/ca-ES/django_forms/README.md @@ -0,0 +1,479 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Security + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/ca-ES/django_installation/README.md b/ca-ES/django_installation/README.md new file mode 100644 index 00000000000..9b024008342 --- /dev/null +++ b/ca-ES/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/ca-ES/django_installation/instructions.md b/ca-ES/django_installation/instructions.md new file mode 100644 index 00000000000..fc965146844 --- /dev/null +++ b/ca-ES/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/ca-ES/django_models/README.md b/ca-ES/django_models/README.md new file mode 100644 index 00000000000..f2a68a8727f --- /dev/null +++ b/ca-ES/django_models/README.md @@ -0,0 +1,201 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/ca-ES/django_orm/README.md b/ca-ES/django_orm/README.md new file mode 100644 index 00000000000..ffe309bd81e --- /dev/null +++ b/ca-ES/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/ca-ES/django_start_project/README.md b/ca-ES/django_start_project/README.md new file mode 100644 index 00000000000..3767c62e17f --- /dev/null +++ b/ca-ES/django_start_project/README.md @@ -0,0 +1,260 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/ca-ES/django_templates/README.md b/ca-ES/django_templates/README.md new file mode 100644 index 00000000000..db2d20c4d4e --- /dev/null +++ b/ca-ES/django_templates/README.md @@ -0,0 +1,108 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/ca-ES/django_urls/README.md b/ca-ES/django_urls/README.md new file mode 100644 index 00000000000..d37a5e3c2fd --- /dev/null +++ b/ca-ES/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/ca-ES/django_views/README.md b/ca-ES/django_views/README.md new file mode 100644 index 00000000000..ab271e0914f --- /dev/null +++ b/ca-ES/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/ca-ES/dynamic_data_in_templates/README.md b/ca-ES/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..5a6ef017adf --- /dev/null +++ b/ca-ES/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/ca-ES/extend_your_application/README.md b/ca-ES/extend_your_application/README.md new file mode 100644 index 00000000000..c70a2db97ff --- /dev/null +++ b/ca-ES/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/ca-ES/how_the_internet_works/README.md b/ca-ES/how_the_internet_works/README.md new file mode 100644 index 00000000000..7b2c014c292 --- /dev/null +++ b/ca-ES/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![Figure 1.2](images/internet_3.png) + +It is fascinating, isn't it? But 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - you send messages and you expect some response. 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 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, 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 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! \ No newline at end of file diff --git a/ca-ES/html/README.md b/ca-ES/html/README.md new file mode 100644 index 00000000000..27c81ea68be --- /dev/null +++ b/ca-ES/html/README.md @@ -0,0 +1,227 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is 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 `TemplateDoesNotExist`, try to restart your server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +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 line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to GitHub + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% 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. + +{% 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: + +{% 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 %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/ca-ES/installation/README.md b/ca-ES/installation/README.md new file mode 100644 index 00000000000..b97592acbe8 --- /dev/null +++ b/ca-ES/installation/README.md @@ -0,0 +1,68 @@ +# 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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. + +Good luck! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Installation + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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. \ No newline at end of file diff --git a/ca-ES/intro_to_command_line/README.md b/ca-ES/intro_to_command_line/README.md new file mode 100644 index 00000000000..b95191c95c8 --- /dev/null +++ b/ca-ES/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Your first command (YAY!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/ca-ES/intro_to_command_line/open_instructions.md b/ca-ES/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/ca-ES/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/ca-ES/python_installation/README.md b/ca-ES/python_installation/README.md new file mode 100644 index 00000000000..8470b71f1f4 --- /dev/null +++ b/ca-ES/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/ca-ES/python_installation/instructions.md b/ca-ES/python_installation/instructions.md new file mode 100644 index 00000000000..592aafe0b5d --- /dev/null +++ b/ca-ES/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 the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/ca-ES/python_introduction/README.md b/ca-ES/python_introduction/README.md new file mode 100644 index 00000000000..320bba5ae1e --- /dev/null +++ b/ca-ES/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introducció a Python + +> Algunes parts d'aquest capítol es basen en els tutorials de les Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Anem a escriure una mica de codi! + +## Línia de comandes (prompt) de Python + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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. + +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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, type the `exit()` function + +{% 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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/ca-ES/template_extending/README.md b/ca-ES/template_extending/README.md new file mode 100644 index 00000000000..7f3697b7fd4 --- /dev/null +++ b/ca-ES/template_extending/README.md @@ -0,0 +1,151 @@ +# Template extending + +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. + +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 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 + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/ca-ES/whats_next/README.md b/ca-ES/whats_next/README.md new file mode 100644 index 00000000000..97c41870d93 --- /dev/null +++ b/ca-ES/whats_next/README.md @@ -0,0 +1,43 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](https://twitter.com/djangogirls) to stay up to date. + +### Can you recommend any further resources? + +Yes! There are a *lot* of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. + +#### Django + +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS and JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! \ No newline at end of file diff --git a/ca/GLOSSARY.md b/ca/GLOSSARY.md new file mode 100644 index 00000000000..2e928dda548 --- /dev/null +++ b/ca/GLOSSARY.md @@ -0,0 +1,3 @@ +# code editor + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/ca/README.md b/ca/README.md new file mode 100644 index 00000000000..01736ae0502 --- /dev/null +++ b/ca/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) + +## Introduction + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/ca/SUMMARY.md b/ca/SUMMARY.md new file mode 100644 index 00000000000..7a45700a27d --- /dev/null +++ b/ca/SUMMARY.md @@ -0,0 +1,27 @@ +# Summary + +* [Introduction](README.md) +* [Installation](installation/README.md) +* [Installation (chromebook)](chromebook_setup/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) +* [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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/ca/chromebook_setup/README.md b/ca/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/ca/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/ca/chromebook_setup/instructions.md b/ca/chromebook_setup/instructions.md new file mode 100644 index 00000000000..809281456d3 --- /dev/null +++ b/ca/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/ca/code_editor/README.md b/ca/code_editor/README.md new file mode 100644 index 00000000000..404011f1b7d --- /dev/null +++ b/ca/code_editor/README.md @@ -0,0 +1,11 @@ +# Code editor + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +You're about to write your first line of code, so it's time to download a code editor! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/ca/code_editor/instructions.md b/ca/code_editor/instructions.md new file mode 100644 index 00000000000..cc66fde0da0 --- /dev/null +++ b/ca/code_editor/instructions.md @@ -0,0 +1,31 @@ +Existeixen gran quantitat d'editors diferents, i l'elecció d'un de particular es redueix principalment a gustos personals. La majoria de programdors de Python utilitzen IDEs (Entorns de Desenvolupament Integrat) complexos però extremadament potents, com ara PyCharm. Com a principiant, això és segurament menys adequat; les nostres recomanacions són igualment potents, però molt més simples. + +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 + +El Gedit és un editor gratuït, open-source, disponible per a tots els sistemes operatius. + +[Descarrega'l aquí](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[Descarrega'l aquí](https://www.sublimetext.com/3) + +## Atom + +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. + +[Descarrega'l aquí](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. :) \ No newline at end of file diff --git a/ca/css/README.md b/ca/css/README.md new file mode 100644 index 00000000000..04d5996ae52 --- /dev/null +++ b/ca/css/README.md @@ -0,0 +1,304 @@ +# 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 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? 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: https://getbootstrap.com/ + +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: + +{% 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! + +![Figure 14.1](images/bootstrap1.png) + +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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +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. 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 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 + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +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. :) 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 be overriden by 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 %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 + +``` + +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). + +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; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Great! + +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 + +``` + +And now add a class `post` to your `div` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/ca/deploy/README.md b/ca/deploy/README.md new file mode 100644 index 00000000000..b44e2eaaf73 --- /dev/null +++ b/ca/deploy/README.md @@ -0,0 +1,260 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ 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) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. + +Hit **Save** and then go back to the **Web** tab. + +We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. + +## Debugging tips + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: + +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. + +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. + +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? + +- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. + +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +And remember, your coach is here to help! + +# You are live! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! \ No newline at end of file diff --git a/ca/deploy/install_git.md b/ca/deploy/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/ca/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/ca/deploy/signup_pythonanywhere.md b/ca/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/ca/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/ca/django/README.md b/ca/django/README.md new file mode 100644 index 00000000000..c62c145305b --- /dev/null +++ b/ca/django/README.md @@ -0,0 +1,27 @@ +# What is Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +Of course, the description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will simply start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/ca/django_admin/README.md b/ca/django_admin/README.md new file mode 100644 index 00000000000..46a5afbb500 --- /dev/null +++ b/ca/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/ca/django_forms/README.md b/ca/django_forms/README.md new file mode 100644 index 00000000000..1d9efebffe4 --- /dev/null +++ b/ca/django_forms/README.md @@ -0,0 +1,447 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? + +## URL + +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```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` we add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## Security + +Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to Github: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/ca/django_installation/README.md b/ca/django_installation/README.md new file mode 100644 index 00000000000..7834993e063 --- /dev/null +++ b/ca/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/ca/django_installation/instructions.md b/ca/django_installation/instructions.md new file mode 100644 index 00000000000..0bc080f7055 --- /dev/null +++ b/ca/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/ca/django_models/README.md b/ca/django_models/README.md new file mode 100644 index 00000000000..7aa11d11732 --- /dev/null +++ b/ca/django_models/README.md @@ -0,0 +1,199 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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 + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/ca/django_orm/README.md b/ca/django_orm/README.md new file mode 100644 index 00000000000..31c47f27764 --- /dev/null +++ b/ca/django_orm/README.md @@ -0,0 +1,218 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Chaining QuerySets + +You can also combine QuerySets by **chaining** them together: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/ca/django_start_project/README.md b/ca/django_start_project/README.md new file mode 100644 index 00000000000..fe1abc7ca9a --- /dev/null +++ b/ca/django_start_project/README.md @@ -0,0 +1,202 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![It worked!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/ca/django_templates/README.md b/ca/django_templates/README.md new file mode 100644 index 00000000000..263eb1fd835 --- /dev/null +++ b/ca/django_templates/README.md @@ -0,0 +1,106 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/ca/django_urls/README.md b/ca/django_urls/README.md new file mode 100644 index 00000000000..c491b27de5c --- /dev/null +++ b/ca/django_urls/README.md @@ -0,0 +1,129 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![Url](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Regex + +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. + +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: + +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern + +Anything else in the URL definition will be taken literally. + +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. + +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: + +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/ca/django_views/README.md b/ca/django_views/README.md new file mode 100644 index 00000000000..07afe091a52 --- /dev/null +++ b/ca/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/ca/dynamic_data_in_templates/README.md b/ca/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..807bb666ebc --- /dev/null +++ b/ca/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/ca/extend_your_application/README.md b/ca/extend_your_application/README.md new file mode 100644 index 00000000000..0bae760be7c --- /dev/null +++ b/ca/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: + +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? Of course: adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`. + +It will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ 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 %} + +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 --all . + $ git status + $ 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/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/ca/how_the_internet_works/README.md b/ca/how_the_internet_works/README.md new file mode 100644 index 00000000000..efd95c3f4b2 --- /dev/null +++ b/ca/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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. + +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![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 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - 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 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, 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 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! \ No newline at end of file diff --git a/ca/html/README.md b/ca/html/README.md new file mode 100644 index 00000000000..004985089c2 --- /dev/null +++ b/ca/html/README.md @@ -0,0 +1,213 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Add the following to your template file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +

Hi there!

+

It works!

+ +``` + +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 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `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, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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.

+
+ + +``` + +We've created three `div` sections here. + +* 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to Github + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% 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: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **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): + +{% 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. + +{% 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: + +{% 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 + $ git pull + [...] + + +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. + +* 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. :) \ No newline at end of file diff --git a/ca/install_git.md b/ca/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/ca/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/ca/installation/README.md b/ca/installation/README.md new file mode 100644 index 00000000000..a7c627136c8 --- /dev/null +++ b/ca/installation/README.md @@ -0,0 +1,58 @@ +# 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 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. \ No newline at end of file diff --git a/ca/instructions.md b/ca/instructions.md new file mode 100644 index 00000000000..30bd493b11b --- /dev/null +++ b/ca/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/ca/intro_to_command_line/README.md b/ca/intro_to_command_line/README.md new file mode 100644 index 00000000000..5fb6d48dd1f --- /dev/null +++ b/ca/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +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. :) + +> 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 by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/ca/python_installation/README.md b/ca/python_installation/README.md new file mode 100644 index 00000000000..93f81cb42d9 --- /dev/null +++ b/ca/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/ca/python_installation/instructions.md b/ca/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/ca/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/ca/python_introduction/README.md b/ca/python_introduction/README.md new file mode 100644 index 00000000000..c1642302532 --- /dev/null +++ b/ca/python_introduction/README.md @@ -0,0 +1,1062 @@ +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.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. + +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. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, simply type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% 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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% 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! + +{% 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% 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 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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 + +{% 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!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/ca/signup_pythonanywhere.md b/ca/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/ca/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/ca/template_extending/README.md b/ca/template_extending/README.md new file mode 100644 index 00000000000..35997f913d3 --- /dev/null +++ b/ca/template_extending/README.md @@ -0,0 +1,147 @@ +# Template extending + +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. + +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 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 + + +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 %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. 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' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/ca/whats_next/README.md b/ca/whats_next/README.md new file mode 100644 index 00000000000..fbb1d2a7d6e --- /dev/null +++ b/ca/whats_next/README.md @@ -0,0 +1,25 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](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](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). + +Later on, you can try the resources listed below. They're all very recommended! + +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/cs-CZ/GLOSSARY.md b/cs-CZ/GLOSSARY.md new file mode 100644 index 00000000000..3107893bace --- /dev/null +++ b/cs-CZ/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-CZ/README.md b/cs-CZ/README.md new file mode 100644 index 00000000000..1ac284e7d6e --- /dev/null +++ b/cs-CZ/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutoriál + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> 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/ + +## Vítej + +Vítej v Django Girls Tutoriálu! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Úvod + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? 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ý, aby jsi 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. + +This tutorial will not magically turn you into a programmer. Jestli chceš být dobrý programátor, 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 jsi se necítila zastrašena technologií. + +Doufáme, že se nám podaří ti přiblížit tuto technologii tak, aby jsi ji měla stejně ráda jako my! + +## Co se naučíš během kurzu? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +Tvá aplikace (více či méně) bude vypadat takto: + +![Figure 0.1](images/application.png) + +> 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). 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, [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. + +## O kurzu a přispěvatelích + +Tento kurz je provozován [DjangoGirls](https://djangogirls.org/). Pokud najdeš nějaké chyby, nebo chceš aktualizovat návod, prosím,[postupuj podle pokynů pro přispívající](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## Would you like to help us translate the tutorial into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/cs-CZ/SUMMARY.md b/cs-CZ/SUMMARY.md new file mode 100644 index 00000000000..080c990996d --- /dev/null +++ b/cs-CZ/SUMMARY.md @@ -0,0 +1,35 @@ +# Shrnutí + +* [Úvod](README.md) +* [Instalace](installation/README.md) + * [Command Line](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Code Editor](installation/README.md#code-editor) + * [Virtual Environment](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Installation (chromebook)](chromebook_setup/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 URLs](django_urls/README.md) +* [Django views – time to create!](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 – make it pretty](css/README.md) +* [Rozšiřování šablon](template_extending/README.md) +* [Rozšíření tvé aplikace](extend_your_application/README.md) +* [Django formuláře](django_forms/README.md) +* [Co dál?](whats_next/README.md) \ No newline at end of file diff --git a/cs-CZ/chromebook_setup/README.md b/cs-CZ/chromebook_setup/README.md new file mode 100644 index 00000000000..802d9c77ac9 --- /dev/null +++ b/cs-CZ/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook setup + +> **Poznámka** Pokud jsi již prošla [instalačními kroky](../installation/README.md), není třeba to znovu dělat – můžeš přeskočit přímo vpřed na [Úvod do Pythonu](../python_introduction/README.md). + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/cs-CZ/chromebook_setup/instructions.md b/cs-CZ/chromebook_setup/instructions.md new file mode 100644 index 00000000000..2079bce2c8b --- /dev/null +++ b/cs-CZ/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Pokud nepoužíváš Chromebook, můžeš [přeskočit přímo na tuto sekci](http://tutorial.djangogirls.org/en/installation/#install-python). Pokud Chromebook používáš, postup instalace se bude trochu lišit. Takže zbytek návodu k instalaci můžeš ignorovat. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Cloud IDE je nástroj, který ti umožňuje využívat editor kódu a přístup k počítači běžícím na internetu, kde můžeš instalovat, psát a spouštět software. V průběhu tutoriálu se Cloud IDE bude chovat jako tvůj *lokální počítač*. Příkazy budeš psát stále pomocí příkazové řádky v terminálu stejně jako tví spolužáci na OS X, Ubuntu nebo Windows, ale tvůj terminál bude propojený s počítačem běžícím někde jinde, což je řešeno pomocí Cloud IDE. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). Můžeš si vybrat jedno z Cloud IDE řešení a následovat instrukce nastavení pro zvolený typ. + +#### PaizaCloud ID + +1. Jdi na [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Zaregistruj se nebo se přihlaš ke svému účtu, pokud již registrovaná jsi. +3. Klikni na *Nový Server* a vyber možnost Django App. +4. Klikni na tlačítko Terminál (na levé straně okna). + +Nyní bys měla vidět rozhraní s postranním panelem a tlačítka nalevo. Klikni na tlačítko Terminál, kde po otevření příkazové řádky uvidíš něco jako: + +{% filename %}Terminal{% endfilename %} + + $ + + +Terminál v PaizaCloud IDE je připraven a čeká na tvé příkazy. Můžeš měnit velikost okna, pokud ti nevyhovuje velikost zobrazení. + +#### AWS Cloud9 + +Momentálně Cloud9 vyžaduje, aby ses přihlásila pomocí AWS účtu a zadala jako platební metodu tvou platební kartu. + +1. Nainstaluj si Cloud9 z odkazu [Chrome webový obchod](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Běž na [c9.io](https://c9.io) a klikni na *Get started with AWS Cloud9* +3. Přihlaš se pomocí svého AWS účtu (vyžaduje zadání platebních údajů, ale bude možné využívat jej zdarma bez placení). +4. V AWS nástěnce vlož *Cloud9* ve vyhledávacím políčku a dej vyhledat. +5. Na Cloud9 nástěnce klikni na *Vytvořit prostředí* +6. Pojmenuj to jako *django-girls* +7. Zatímco se konfiguruje nastavení, pro "Typ prostředí" vyber možnost *Vytvořit novou instanci pro prostředí (EC2)* a jako "Typ instance" zvol *t2.micro* (mělo by zmiňovat ""Free-tier eligible."). Výchozí nastavení plateb a výdajů lze nechat tak, jak je a stejně pokračovat i u dalších nastavení. +8. Klikni na *Další krok* +9. Klikni na *Vytvořit prostředí* + +Nyní bys měla vidět rozhraní s postranním panelem a velkým hlavním oknem, kde bude nějaký text a malé okno v dolní části stránky, které vypadá přibližně takto: + +{% filename %}bash{% endfilename %} + + yourusername:~/workspace $ + + +Tato dolní část je tvůj terminál. Můžeš jej použít pro zadání příkazů pro vzdálený Cloud9 počítač. Můžeš měnit velikost okna, jak potřebuješ. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### Virtuální prostředí + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(note that on the last line we use a tilde followed by an equal sign: `~=`). + +### GitHub + +Make a [GitHub](https://github.com) account. + +### Python Anywhere + +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 for 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). \ No newline at end of file diff --git a/cs-CZ/code_editor/README.md b/cs-CZ/code_editor/README.md new file mode 100644 index 00000000000..8ce898b2940 --- /dev/null +++ b/cs-CZ/code_editor/README.md @@ -0,0 +1,11 @@ +# Editor zdrojového kódu + +> Čtení na doma: tato kapitola je pokryta ve videu [Instalujeme pro Python & Editor kódu](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s). + +Právě se chystáš napsat svůj první řádek kódu, takže je čas sáhnout po editoru kódu! + +> **Poznámka** POkud používáš Chromebook přeskoč tuto kapitolu a ujisti se, že následuješ pokyny pro [Nastavení Chromebooku](../chromebook_setup/README.md). Cloudové IDE, které si vybereš (Paiza Cloud nebo AWS Cliud9) zahrnuje editor kódu a když otevřeš soubor ve tvém IDE z nabídky souborů, automaticky použije editor kódu. +> +> **Poznámka** Je možné, že jsi to již udělala dříve v [kapitole o instalaci](../installation/README.md) – pokud ano, můžeš přeskočit rovnou an další kapitolu!! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/cs-CZ/code_editor/instructions.md b/cs-CZ/code_editor/instructions.md new file mode 100644 index 00000000000..9131a89dca5 --- /dev/null +++ b/cs-CZ/code_editor/instructions.md @@ -0,0 +1,37 @@ +Existuje mnoho různých editorů a z velké části se výběr scvrkává na osobní preference. Většina programátorů 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. + +## Visual Studio Code + +XPath: /p[3]. Zahrnuje technickou podporu pro tzv. debugging, kompletní možnost práce s Gitem, zvýrazňování syntaxe jazyka, inteligentní pomoc pro psaní kódu, napovědu a možnost refactorovat kód. + +[Stáhnout si jej můžeš zde](https://code.visualstudio.com/) + +## 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 je velmi oblíbený a známý editor s možností využít zkušební verzi zdarma a je dostupný pro všechny operační systémy. + +[Stáhnout si jej můžeš zde](https://www.sublimetext.com/3) + +## Atom + +Atom je další populární editor. Je zdarma, open-source a je k dispozici pro Windows, OS X a Linux. Atom byl vyvinut firmou [GitHub](https://github.com/). + +[Stáhnout si jej můžete zde](https://atom.io/) + +## Proč instalujeme editor kódu? + +Možná přemýšlíte, proč instalujeme speciální editor 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 problém s programy jako Word a Textedit je ten, že ve skutečnosti neprodukují prostý text ale 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 jsou pro tuto práci uzpůsobené tak, že poskytují užitečné pomůcky jako je barevné zvýrazňování různých částí kódu podle jejich významu či automatické uzavírání uvozovek. + +V akci to uvidíme později. Brzy budeš na svůj editor kódu nahlížet jako na jeden ze svých oblíbených nástrojů. :) \ No newline at end of file diff --git a/cs-CZ/css/README.md b/cs-CZ/css/README.md new file mode 100644 index 00000000000..0d4ec82b563 --- /dev/null +++ b/cs-CZ/css/README.md @@ -0,0 +1,330 @@ +# CSS - zkrášli svou stránku! + +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? + +Kaskádové styly (Cascading Style Sheets, CSS) je jazyk používáný pro popis vzhledu a formátu webové stránky napsané ve značkovacím jazyce (jako například HTML). Berte to jako make-up pro naši webovou stránku. ;) + +Ale nechceme začínat od nuly, že? Znovu použijeme něco, co už někdo vytvořil a umístil na Internet aby to mohli ostatní programátoři používat zdarma. Vymýšlení už vymyšlených věcí není zábava. + +## Použijme Bootstrap! + +Bootstrap je jeden z nejpopulárnějších frameworků pro HTML a CSS na vytváření krásných webových stránek: https://getbootstrap.com/ + +Byl vytvořen programátory, kteří pracovali pro Twitter. Nyní je Bootstrap vyvíjen dobrovolníky po celém světě! + +## Instalace Bootstrapu + +Pro instalaci Bootstrapu otevři svůj `.html` soubor v kódovém editoru a přidej tohle do `` sekce: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Nepřidá to žádné soubory do tvého projektu. Jen to ukazuje na soubory, které existují na Internet. Takže do toho, otevři svoji webovou stránku a obnov ji. To je ono! + +![Obrázek 14.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šechna tvá CSS a obrázky. Jejich obsah nezávisí na kontextu požadavku a bude stejný pro každého uživatele. + +### Kam umístit statické soubory pro Django + +Django již ví, kde najít statické soubory pro vestavěnou "admin" aplikaci. Nyní potřebujeme přidat nějaké statické soubory do naší vlastní aplikace, `blog`. + +Uděláš to tak, že vytvoříš složku s názvem `static` uvnitř aplikace blog: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │   └── templates + └── mysite + + +Django bude automaticky hledat jakékoliv složky nazvané "static" uvnitř tvých složek v aplikaci. Poté bude schopný použít jejich obsah jako statické soubory. + +## Tvůj první soubor CSS! + +Pojďme vytvořit nějaký CSS soubor a přidat vlastní styly pro tvou webovou stránku. 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. + +Zde nebudeme zacházet příliš do detailů a učit se CSS nebo jej přizpůsobovat. Pokud se budeš chtít naučit více o CSS, na konci této stránky najdeš doporučení na CSS kurz zdarma. + +Ale pojďme něco málo udělat. Možná bychom mohli změnit barvu našich nadpisů? Pro interpretaci barev, počítače používají speciální kódy. Tyto kódy začínají `#` a následuje 6 písmen(A-F) a číslic(0-9). Například kód pro modrou barvu bude vypadat takto: `#0000FF`. Kódy všech barev můžeš najít například zde: http://www.colorpicker.com/. Můžeš také použít [předdefinované barvy](http://www.w3schools.com/colors/colors_names.asp), `červená/red` a `zelená/green`. + +V souboru `blog/static/css/blog.css` přidej následující kód: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1` je CSS selector. Toto znamená, že aplikujeme naše styly na každý element `a` uvnitř elementu `h1` , selektor `h2` dělá to samé pro elementy `h2`. Takže když máme něco jako `

odkaz

`, použije se styl `h1`. V tomto případě říkáme, že barvu elementu měníme na `#C25100`, což je oranžová. Nebo zde můžeš vložit vlastní barvu, ale ujisti se, že bude kontrastní vůči bílé barvě pozadí stránky. + +V CSS souboru určujeme styly pro prvky v souboru HTML. První způsob, jak identifikovat prvky je pomocí názvu elementu. Možná si vzpomeneš na tyto tagy ze sekce HTML. Věci jako `a`, `h1` a `body`jsou všechny příklady názvů elementů. Také identifikujeme elementy podle atributu `class` nebo atributu `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. For example, you could identify the following element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +Více si můžeš přečíst [CSS Selectoryna w3schools](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 úplný začátek: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +Právě zde načítáme statické soubory. :) mezi značkami `` a `` , po odkazech na Bootstrap CSS soubory přidejte tento řádek: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Prohlížeč čte soubory v pořadí, ve kterém jsou zadány, takže se musíme ujistit, že jsme na správném místě. V opačném případě může být kód v našem souboru přepsán kódem z Bootstrap souborů. Právě jsi řekla naší šabloně, kde je umístěn náš soubor CSS. + +Soubor by měl nyní vypadat takto: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, ulož soubor a aktualizuj stránky! + +![Obrázek 14.2](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! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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](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`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Stejně jako předtím, zkontroluj pořadí a místo před odkazem na `blog/static/css/blog.css`. Tento řádek importuje font s názvem *Lobster* z Google Fonts (https://www.google.com/fonts). + +Najdi blok `h1 deklarací` (kód mezi závorkami `{` a `}`) v CSS souboru `blog/static/css/blog.css`. Nyní přidej řádek `font-family: 'Lobster';` mezi závorkami a obnov stránku: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Obrázek 14.3](images/font.png) + +Skvěle! + +Jak bylo uvedeno výše, CSS má koncepci tříd. Ty ti umožňují pojmenovat část HTML kódu a aplikovat styly pouze na danou část, aniž by to ovlivnilo ostatní části. To může být super užitečné! Možná máš dva prvky 'div' , které dělají něco jiného (jako je hlavička a tvůj příspěvek). Třída ti může pomoci, aby element vypadal jinak. + +Go ahead and name some parts of the HTML code. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ 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`: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Pak obklopující HTML kód, který zobrazuje příspěvek s deklaracemi tříd. Nahraď tímto: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Tyto soubory ulož a aktualizuj své webové stránky. + +![Obrázek 14.4](images/final.png) + +Jupí! To je paráda, co? Podívej se na kód, který jsme právě vložili, abychom našli místa, kde jsme přidali třídy v HTML a používali je v CSS. Kde bys provedla změnu, pokud chceš, aby datum bylo tyrkysové? + +Neboj se trochu pohrát s tímto CSS a pokus se některé věci změnit. Hraní s CSS ti pomůže pochopit, co dělají různé věci. Pokud něco rozbiješ, nedělej si starosti - vždy to můžeš vrátit zpět! + +Opravdu doporučujeme vzít zdarma online kurzy "Základní HTML & HTML5" a "Základní CSS" na [freeCodeCamp](https://learn.freecodecamp.org/). Mohou ti pomoci naučit se, jak udělat tvé webové stránky hezčí pomocí HTML a CSS. + +Připravena na další kapitolu?! :) \ No newline at end of file diff --git a/cs-CZ/deploy/README.md b/cs-CZ/deploy/README.md new file mode 100644 index 00000000000..0fcff61f8ba --- /dev/null +++ b/cs-CZ/deploy/README.md @@ -0,0 +1,246 @@ +# 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. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! 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. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +Další externí službu, kterou budeme používa je [GitHub](https://www.github.com), 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é! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% 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: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. Měla by jsi být ve složce `djangogirls`. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +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: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Poznámka:** Tečka na začátku názvu souboru je důležitá! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +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. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + 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: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/cs-CZ/deploy/install_git.md b/cs-CZ/deploy/install_git.md new file mode 100644 index 00000000000..50b1f48a566 --- /dev/null +++ b/cs-CZ/deploy/install_git.md @@ -0,0 +1,52 @@ +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 "sledovat změny" ve slovních procesorových programech (např. Microsoft Word nebo LibreOffice spisovatel), ale mnohem silnější. + +## Instalace Git + + + +Git si můžeš stáhnout z [git-scm.com](https://git-scm.com/). Klikej na "další další další" ve všech krocích s vyjímkou 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ý. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/cs-CZ/deploy/signup_pythonanywhere.md b/cs-CZ/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..555e36731dd --- /dev/null +++ b/cs-CZ/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use it for hosting our site, live and on the Internet. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/cs-CZ/django/README.md b/cs-CZ/django/README.md new file mode 100644 index 00000000000..ae991cd6c8d --- /dev/null +++ b/cs-CZ/django/README.md @@ -0,0 +1,27 @@ +# Co je Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. 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. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Proč potřebuješ framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Představ si poštovní schránku (port). Ta sleduje příchozí zprávy (požadavky). Podobně se chová webový server. The web server reads the letter and then sends a response with a webpage. Ale když chceš něco poslat, musíš mít nějaký obsah. A Django je něco, co ti pomůže vytvořit tento obsah. + +## Co se stane, když někdo požaduje webové stránky ze serveru? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *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! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Možná, že uživatel chtěl změnit něco v datech? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/cs-CZ/django_admin/README.md b/cs-CZ/django_admin/README.md new file mode 100644 index 00000000000..099983c4ea0 --- /dev/null +++ b/cs-CZ/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```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 čas se podívat na náš Post model. Nezapomeň spustit `Pythonu manage.py runserver` v konzoli www serveru. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/cs-CZ/django_forms/README.md b/cs-CZ/django_forms/README.md new file mode 100644 index 00000000000..b8570890ca5 --- /dev/null +++ b/cs-CZ/django_forms/README.md @@ -0,0 +1,479 @@ +# Django formuláře + +Poslední věc, kterou chceme udělat na našich webových stránkách, je vytvořit příjemný způsob, jak přidávat a upravovat příspěvky na blogu. Django `admin` je super, ale je to dost těžko přizpůsobitelné a upravitelné do hezčí podoby. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +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, formuláře mají své vlastní soubory: `forms.py`. + +Potřebujeme vytvořit soubor s tímto názvem v našem adresáři `blog`. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, jak asi předpokládáš, je jméno našeho formuláře. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Dále zde máme `třídu Meta`, kde řekneme Djangu, který model by měl být použít 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. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +A je to! Vše, co musíme udělat, je použít formulář ve *view* a zobrazit ho v šabloně. + +So once again we will create a link to the page, a URL, a view and a template. + +## Odkaz na stránku s formulářem + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Šablona + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* Potřebujeme tlačítko `Uložit`. Vytvoříme HTML tlačítko: `< button type="submit"> Uložit < / button>`. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. Toto je velmi důležité, protože tak vytvoříme bezpečnější formulář! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Ukládání formuláře + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Ověření formuláře + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Upravit formulář + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Zabezpečení + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## Ještě jedna věc: čas nasadit aplikaci! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Pak v [Bash konzoli PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/cs-CZ/django_installation/README.md b/cs-CZ/django_installation/README.md new file mode 100644 index 00000000000..e16030a81af --- /dev/null +++ b/cs-CZ/django_installation/README.md @@ -0,0 +1,7 @@ +# Instalace Django + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/cs-CZ/django_installation/instructions.md b/cs-CZ/django_installation/instructions.md new file mode 100644 index 00000000000..e024bc9bca1 --- /dev/null +++ b/cs-CZ/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. 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ď 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ář. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +Pro tento kurz budeme používat nový adresář `djangogirls` vytvořený v domovském adresáři: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +Vytvoříme virtualenv, s názvem `myvenv`. Obecný příkaz bude vypadat takto: + +{% filename %}command-line{% endfilename %} + + $ Python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. Můžeš použít i jiné jméno, ale používej malá písmena a nepoužívej mezery, diakritiku nebo speciální znaky. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ 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. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> 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`. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Práce s virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Spusť virtuální prostředí: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/cs-CZ/django_models/README.md b/cs-CZ/django_models/README.md new file mode 100644 index 00000000000..835c360b5ce --- /dev/null +++ b/cs-CZ/django_models/README.md @@ -0,0 +1,201 @@ +# Django modely + +Nyní chceme vytvořit něco, co bude ukládat všechny příspěvky na našem blogu. Ale aby jsme to mohli udělat, musíme si nejdříve říct něco o `objektech`. + +## Objekty + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +Co tedy je objekt? Je to kolekce vlastností a činností. Zní to divně, ale dáme ti příklad. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + 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? Chceme vytvořit blog, ne? + +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? It would be also nice to know who wrote it – so we need an author. 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, že ano? + +Takže budeme potřebovat metodu `publish`. + +Vzhledem k tomu, že už víme, co chceme dosáhnout, můžeme začít modelování v Django! + +## Django model + +Nyní víme jaký objekt chceme vytvořit, tak můžeme přistoupit k tvorbě Django modelu pro náš příspěvek v blogu. + +A model in Django is a special kind of object – it is saved in the `database`. Databáze je soubor dat. Je to místo, ve kterém 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. This is the default Django database adapter – it'll be enough for us right now. + +Model v databázi si lze představit jako tabulku s řádky (data) a sloupci (údaje). + +### Vytvoření aplikace + +Abychom udrželi 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): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Vytvoření modelu pro blog post + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. Tato konvence se v Pythonu používá často. Někdy je také nazýváme "dunder" (zktratka pro "Double-UNDERscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` je speciální klíčové slovo, které říká, že definujeme objekt. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models. Model` znamená, že Post je Django Model, takže Django ví, že by to mělo být uloženo v databázi. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Vytvoření tabulek pro modely v databázi + +The last step here is to add our new model to our database. Nejprve musíme dát Djangu vědět, že máme nějaké změny v modelu (které jsme právě vytvořili). (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/cs-CZ/django_orm/README.md b/cs-CZ/django_orm/README.md new file mode 100644 index 00000000000..2104d6e5fe1 --- /dev/null +++ b/cs-CZ/django_orm/README.md @@ -0,0 +1,221 @@ +# 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? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +Je snazší naučit se to na příkladu. Pojďme to zkusit, můžeme? + +## Django shell + +Otevři svou lokání konzoli (ne na Python Anywhere) a napiš tento příkaz: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +Mělo by to mít takovýto efekt: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Vytvoř objekt + +Takhle vytvoříš nový Post objekt v databázi: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=ja, title='titulek', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Nejdříve pojďme importovat User model: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +Jaké uživatele máme v naší databázi? Zkus tohle: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Teď můžeme konečně vytvořit příspěvek: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurá! Chceš se podívat jestli to fungovalo? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +A je to tu, další příspěvek v seznamu! + +### Přidej více příspěvků + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filtrování objektů + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. V `Post.objects.all()` použijeme `filter` místo `all`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Teď náš kus kódu vypadá takhle: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Poznámka** Mezi `title` a `contains` jsou dvě podtržítka (`_`). Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +A ten publikujeme pomocí naší metody `publish`: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> 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`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +Můžeme je také seřadit obráceně přidáním `-` na začátek: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> 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 konzoli zadej toto: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/cs-CZ/django_start_project/README.md b/cs-CZ/django_start_project/README.md new file mode 100644 index 00000000000..cc4936f3775 --- /dev/null +++ b/cs-CZ/django_start_project/README.md @@ -0,0 +1,259 @@ +# Tvůj první Django projekt! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Ochranou známku pro Django-marcador drží Markus Zapke-Gründemann et al. + +We're going to create a small 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 Django, 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 by jsi 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, aby jsme mohli najít důležité věci. + +> Nezapomeň spouštět vše ve svém virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. Jak se to dělá jsme vysvětlili v kapitole **Django instalace** v části **práce s virtualenv**. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin 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). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe 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). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`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 + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +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, kterou nezapomeň, žá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. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +Bylo by hezké mít správný čas na našich stránkách. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +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`: + +{% filename %}mysite/settings.py{% endfilename %} + +```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 vidět něco takového: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +A máme hotovo! Čas spustit webový server a měla by jsi vidět naše fungující webové stránky! + +## Starting the web server + +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`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/cs-CZ/django_templates/README.md b/cs-CZ/django_templates/README.md new file mode 100644 index 00000000000..ee5edfa740e --- /dev/null +++ b/cs-CZ/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? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Zobraz šablonu se seznamem příspěvků + +V předchozí kapitole jsme dali 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: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Zkus to ve své šabloně `blog/templates/blog/post_list.html`. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Ulož soubor a obnov stránku, abys viděla výsledek: + +![Figure 13.1](images/step1.png) + +Jak vidíš, dostali jsme toto: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +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: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Zkus udělat tohle ve své šabloně. + +![Figure 13.2](images/step2.png) + +Funguje to! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. Můžeš smíchat HTML tagy se šablonovými. Naše `body` bude vypadat takhle: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ 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](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? Přistupujeme k datům v každém poli defnovaném v našem `Post` modelu. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## Ještě jedna věc + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Pak se přihlaš do [PythonAnywhere](https://www.pythonanywhere.com/consoles/) s jdi do **Bash konzole** (nebo vytvoř novou) a zadej: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/cs-CZ/django_urls/README.md b/cs-CZ/django_urls/README.md new file mode 100644 index 00000000000..012bb932275 --- /dev/null +++ b/cs-CZ/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## Co je adresa URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` je adresa URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Každá stránka na internetu potřebuje svou vlastní URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## Jak fungují URL v Djangu? + +Pojďme otevřít `mysite/urls.py` soubor v tvém zvoleném editoru kódu a uvidíme, jak vypadá: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/cs-CZ/django_views/README.md b/cs-CZ/django_views/README.md new file mode 100644 index 00000000000..39cab33e993 --- /dev/null +++ b/cs-CZ/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Nejdříve se musíme zbavit chyb, které jsme vytvořili 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. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +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, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Další chyba! Přečti si, co je špatně nyní: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/cs-CZ/dynamic_data_in_templates/README.md b/cs-CZ/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..9e1b2f6ee94 --- /dev/null +++ b/cs-CZ/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# 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ě? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +To je přesně to, co *views* mají dělat: spojovat modely a šablony. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Vzpomínáš si, jak jsme mluvili o zahrnování kódu napsaného v různých souborech? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Potom importujeme název modelu (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Vezmi, prosím, na vědomí, že jsme vytvořili *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. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. Potřebujeme je pojmenovat (teď zůstaneme u `'posts'`). :) Mělo by to vypadat takhle: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +A nakonec by náš `blog/views.py` soubor měl vypadat takhle: + +{% filename %}blog/views.py{% endfilename %} + +```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! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/cs-CZ/extend_your_application/README.md b/cs-CZ/extend_your_application/README.md new file mode 100644 index 00000000000..9d14b557357 --- /dev/null +++ b/cs-CZ/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Rozšíření tvé aplikace + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Vytvoření šablony odkazu na post detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Vytváříme adresu URL na detail příspěvku + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Přidání view pro detail příspěvku + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/cs-CZ/how_the_internet_works/README.md b/cs-CZ/how_the_internet_works/README.md new file mode 100644 index 00000000000..14d703d6b28 --- /dev/null +++ b/cs-CZ/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# Jak funguje internet + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Webové prohlížeče jsou navrženy tak, aby tomuto kódu rozuměly, následovaly instrukce a prezentovaly soubory, ze kterých je tvá stránka vytvořena, přesně tak jak chceš. + +Jako s každým souborem, 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. That's why they're called *servers* – because they *serve* you data. + +OK, but you want to know how the Internet looks, right? + +Nakreslili jsme pro tebe obrázek! Vypadá takhle: + +![Figure 1.1](images/internet_1.png) + +Vypadá to jako pěkný bordel, že? In fact it is a network of connected machines (the above-mentioned *servers*). 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](images/internet_3.png) + +Není to fascinující? But 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. + +Vypadá to takhle: + +![Figure 1.3](images/internet_2.png) + +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!" + +Tvůj dopis se pošle na tobě 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](images/internet_4.png) + +That's how it works - you send messages and you expect some response. Instead of paper and pen you use bytes of data, but the idea is the same! + +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. 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, a stamp, etc. Také používáš jazyk kterému adresát rozumí, že ano? 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). + +Since this is a Django tutorial, you might ask what Django does. 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ů. :) + +Enough talk – time to create! \ No newline at end of file diff --git a/cs-CZ/html/README.md b/cs-CZ/html/README.md new file mode 100644 index 00000000000..e87a7908033 --- /dev/null +++ b/cs-CZ/html/README.md @@ -0,0 +1,227 @@ +# Úvod do HTML + +Co je to šablona, se ami ptáš? + +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**). + +## Co je HTML? + +HTML is a code that is interpreted by your web browser – such as Chrome, Firefox or Safari – to display a web page for the user. + +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 representují **elementy** značkovacího jazyka (Markup. + +## Tvá první šablona! + +Vytvoření šablony znamená vytvoření souboru šablony. Všechno je soubor, dobř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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is a useful naming convention that makes life easier when things start to get more complicated.) + +A teď vytvoř soubor `post_list.html` (pro teď ho nech prázdný) uvnitř adresáře `blog/templates/blog`. + +Podívej se jak tvá stránka vypadá teď: http://127.0.0.1:8000/ + +> Pokud se ti stále zobrazuje chyba`TemplateDoesNotExists`, zkus restartovat server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +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 line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and 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 sdělili co na té stránce skutečně je. + +For example, you can put a web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Ulož soubor a načti znovu svou stránku. + +![Figure 11.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ě jsi si 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: `

`. + +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. + +## 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ů: + +* `

A heading

` for your most important heading +* `

Pod-nadpis

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

A sub-sub-heading

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

A paragraph of text

` +* `text` zvýrazňuje tvůj text +* `text` hodně zvýrazňuje tvůj text +* `
` goes to another line (you can't put anything inside br and there's no closing tag) +* `link` vytváří odkaz +* `
  • První položka seznamu
  • second item
` vytváří seznam, zrovna jako tento! +* `
` definuje sekce stránky +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +To nám dá následující efekt: + +![Figure 11.4](images/step6.png) + +Jupííí! 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. + +## Ještě jedna věc: nasaďme to! + +Bylo by fajn vidět všecho tohle venku a živé na internetu, že jo? Pojďme udělat další PythonAnywhere nasazení (deploy): + +### Commit, and push your code up to 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): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +Než nahrajeme všechny soubory, zkontrolujme co bude `git` nahrávat (všechny soubory, které bude `git` nahrávat, se zobrazí zeleně): + +{% filename %}command-line{% endfilename %} + + $ 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ěnili. 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. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "Změněn HTML kód stránek." + + +> **Note** Make sure you use double quotes around the commit message. + +Once we've done that, we upload (push) our changes up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git push + + +### Stáhni svůj nový kód na PythonAnywhere a načti webovou aplikaci + +* Otevři [stránku s konzolí na PythonAnywhere](https://www.pythonanywhere.com/consoles/) a jdi do své **Bash konzole** (nebo začni novou). Potom zadej: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/cs-CZ/installation/README.md b/cs-CZ/installation/README.md new file mode 100644 index 00000000000..0cee7612e07 --- /dev/null +++ b/cs-CZ/installation/README.md @@ -0,0 +1,68 @@ +# Pokud děláš tutoriál doma + +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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. + +Good luck! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Installation + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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. \ No newline at end of file diff --git a/cs-CZ/intro_to_command_line/README.md b/cs-CZ/intro_to_command_line/README.md new file mode 100644 index 00000000000..b5de37b6941 --- /dev/null +++ b/cs-CZ/intro_to_command_line/README.md @@ -0,0 +1,440 @@ +# Úvod k příkazové řádce + +> 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! :) + +**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. + +> **Note** Please note that throughout this book we use the terms 'directory' and 'folder' interchangeably but they are one and the same thing. + +## 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. It's much like Windows Explorer or Finder on the Mac, but without the graphical interface. Další jména pro příkazovou řádku jsou: *cmd*, *prompt*, *command line*, *konzole* nebo *terminál*. + +## Otevři rozhraní příkazové řádky + +To start some experiments we need to open our command-line interface first. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## Příkazová řádka + +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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Tvůj první příkaz (hurá!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Základy + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Aktuální složka + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Aplikace + Desktop + Stažené soubory + Hudba... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Řešení: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, huh? :) + +## Shrnutí + +Here is a summary of some useful commands: + +| Příkaz (Windows) | Příkaz (Mac OS / Linux) | Popis | Příklad | +| ----------------------- | ----------------------- | -------------------------- | -------------------------------------------------- | +| zavření příkazové řádky | zavření příkazové řádky | Zavřít okno | **zavření příkazové řádky** | +| cd | cd | změnit adresář | **cd test** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (or del) | rm | delete a file | **del c:\test\test.txt** | +| rmdir /S | rm -r | delete a directory | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Připraveno? + +Let's dive into Python! \ No newline at end of file diff --git a/cs-CZ/intro_to_command_line/open_instructions.md b/cs-CZ/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/cs-CZ/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/cs-CZ/python_installation/README.md b/cs-CZ/python_installation/README.md new file mode 100644 index 00000000000..84715c1173f --- /dev/null +++ b/cs-CZ/python_installation/README.md @@ -0,0 +1,15 @@ +# 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 čitelný lidským bytostem (nejen strojům!). This is why it looks simpler than other programming languages, but don't worry – Python is also really powerful! + +# Instalace Pythonu + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/cs-CZ/python_installation/instructions.md b/cs-CZ/python_installation/instructions.md new file mode 100644 index 00000000000..592aafe0b5d --- /dev/null +++ b/cs-CZ/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 the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/cs-CZ/python_introduction/README.md b/cs-CZ/python_introduction/README.md new file mode 100644 index 00000000000..6ac95a12d78 --- /dev/null +++ b/cs-CZ/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Úvod do Pythonu + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Let's write some code! + +## Interaktivní režim Pythonu + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Tvůj první příkaz v Pythonu! + +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, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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… + +## Řetězce + +How about your name? Type your first name in quotes like this: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ahoj" + "Ola" +'Ahoj Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Shrnutí + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Chyby + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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. + +- Funkce `str`převede věci do **řetězců** +- Funkce `int` převede věci na **celá čísla** + +> Important: we can convert numbers into text, but we can't necessarily convert text into numbers – what would `int('hello')` be anyway? + +## Proměnné + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} 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. + +Hraj si s tím chvilku, ať vidíš co se s tím dá dělat! + +## Funkce print + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## Seznamy + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Slovníky + +> 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 substituting your own information, too): + +{% 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: + +- 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). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it in the next line. + +- Potřebuješ jen seřazenou sekvenci položek? Použij seznam. +- Pokud potřebuješ přiřadit hodnotám klíče, aby jsi je mohla později efektivně vyhledávat (klíčem)? Používej slovník. + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 learned another amazing thing. + +### Shrnutí + +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 + +Excited for the next part? :) + +## Porovnávání věcí + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- 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 + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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. + +## Logic hodnoty/Booleany + +Incidentally, you just learned about a new type of object in Python. It's called **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Ulož 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: + +- Ukončit interaktivní režim Pythonu +- Otevřít tvůj zvolený editor kódu +- Ulož nějaký kód do nového pythnovského souboru +- Spusť ho! + +Chceš-li opustit interaktivní režim Pythonu, který jsme dosud používali jednoduše zadej funkci `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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +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. + +> **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. To se nazývá "zvýrazňování syntaxe" a je to opravdu užitečná funkce při kódování. 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). To je jeden z důvodů, proč používáme editory kódu. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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. + +### Co když podmínka není pravdivá? + +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') +else: + print('5 is not greater than 2') +``` + +Pokud je výraz pravdivý po spuštění se vytiskne: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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 + dokonalé, můžete slyšet všechny detaily + + +## 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. + +### Shrnutí + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Vlastní funkce! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + + +Congratulations! You just learned how to write functions! :) + +## Smyčky/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: +``` + +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. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 by that we mean it includes the first value, but not the last. + +## Shrnutí + +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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/cs-CZ/template_extending/README.md b/cs-CZ/template_extending/README.md new file mode 100644 index 00000000000..2d933811652 --- /dev/null +++ b/cs-CZ/template_extending/README.md @@ -0,0 +1,151 @@ +# 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. + +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 a base template + +Základní šablona je šablona, kterou rozšíříme 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 + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Pak v `base.html`, nahraď celé `< body >` (vše mezi `< body >` a `< / body >`) tímto: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). Hned ti ukážeme jak to udělat. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Takto:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/cs-CZ/whats_next/README.md b/cs-CZ/whats_next/README.md new file mode 100644 index 00000000000..319212081e2 --- /dev/null +++ b/cs-CZ/whats_next/README.md @@ -0,0 +1,43 @@ +# Co dál? + +Můžeš si pogratulovat! **Jsi naprosto úžasná**. Jsme na tebe hrdí! <3 + +### Co mám dělat teď? + +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](https://twitter.com/djangogirls) to stay up to date. + +### Můžete mi doporučit nějaké další zdroje? + +Yes! There are a *lot* of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. + +#### Django + +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS and JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! \ No newline at end of file diff --git a/cs/README.md b/cs/README.md index 5ad33b27ddd..0334d39dd10 100755 --- a/cs/README.md +++ b/cs/README.md @@ -1,53 +1,51 @@ # 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/ +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) -## Úvod +> 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/ -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? +## Welcome -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. +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. -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. +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) -Doufáme, že se nám podaří přiblížit ti tuto technologii tak, abys ji měla stejně ráda jako my! +## Úvod -## Co se naučíš během kurzu? +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? 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ý, aby jsi zkusila něco naprogramovat sama? -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! +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. -Tvá aplikace bude (více či méně) vypadat takto: +This tutorial will not magically turn you into a programmer. Jestli chceš být dobrý programátor, 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 jsi se necítila zastrašena technologií. -![Figure 0.1][2] +Doufáme, že se nám podaří ti přiblížit tuto technologii tak, aby jsi ji měla stejně ráda jako my! - [2]: images/application.png +## Co se naučíš během kurzu? -> 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! +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! -OK, [začněme od začátku...][3] +Tvá aplikace (více či méně) bude vypadat takto: - [3]: ./how_the_internet_works/README.md +![Figure 0.1](images/application.png) -## O kurzu a přispěvatelích +> 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). 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! -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]. +OK, [let's start at the beginning…](./how_the_internet_works/README.md) - [4]: https://djangogirls.org/ - [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md +## Following the tutorial at home -## Český překlad +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. -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. +In every chapter already covered, there is a link that points to the correct video. -## Chtěla bys nám pomoci přeložit návod do jiných jazyků? +## O kurzu a přispěvatelích -V současné době jsou překlady provozovány na platformě crowdin.com na adrese: +Tento kurz je provozován [DjangoGirls](https://djangogirls.org/). Pokud najdeš nějaké chyby, nebo chceš aktualizovat návod, prosím,[postupuj podle pokynů pro přispívající](https://github.com/DjangoGirls/tutorial/blob/master/README.md). -https://crowdin.com/project/django-girls-tutorial +## Would you like to help us translate the tutorial into other languages? -Pokud tvůj jazyk není uveden v seznamu na crowdin, prosím, [založ nový požadavek][6] pro přidání dalšího jazyka. +Currently, translations are being kept on crowdin.com platform at: + +https://crowdin.com/project/django-girls-tutorial - [6]: https://github.com/DjangoGirls/tutorial/issues/new +If your language is not listed on [crowdin](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/cs/SUMMARY.md b/cs/SUMMARY.md index 44793ad9d19..e1eafb7ecaa 100755 --- a/cs/SUMMARY.md +++ b/cs/SUMMARY.md @@ -1,26 +1,27 @@ # 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) +* [Úvod](README.md) +* [Instalace](installation/README.md) +* [Installation (chromebook)](chromebook_setup/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 – time to create!](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 – make it pretty](css/README.md) +* [Rozšiřování šablon](template_extending/README.md) +* [Rozšíření tvé aplikace](extend_your_application/README.md) +* [Django formuláře](django_forms/README.md) +* [Co dál?](whats_next/README.md) \ No newline at end of file diff --git a/cs/chromebook_setup/README.md b/cs/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/cs/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/cs/chromebook_setup/instructions.md b/cs/chromebook_setup/instructions.md new file mode 100644 index 00000000000..809281456d3 --- /dev/null +++ b/cs/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/cs/code_editor/README.md b/cs/code_editor/README.md index f91d7968087..a84ad55e645 100755 --- a/cs/code_editor/README.md +++ b/cs/code_editor/README.md @@ -1,7 +1,11 @@ # Editor zdrojového kódu +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + Právě se chystáš napsat svůj první řádek kódu, takže je čas sáhnout po editoru kódu! +> **Poznámka:** Pokud používš Chromebook, pak tuto kapitolu vynechej a řiď se instrukcemi v návodu [Chromebook Setup](../chromebook_setup/README.md). +> > **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 index 9666843aff6..04899c17afe 100755 --- a/cs/code_editor/instructions.md +++ b/cs/code_editor/instructions.md @@ -10,22 +10,22 @@ Gedit je open-source editor. Je k dispozici zdarma pro všechny operační syst ## 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. +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. [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. +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. [Stáhnout si jej můžeš zde](https://atom.io/) -## Proč jsme instalovali editor kódu? +## Proč instalujeme 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). +Prvním důvoden je, že kód musí být psán v **prostém textu** a programy jako Word a Textedit ve skutečnosti produkují bohatý text (s fonty a formátováním) a 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. +Druhým důvodem je, že editory kódu jsou pro tuto práci uzpůsobené tak, že poskytují užitečné pomůcky jako je barevné zvýrazňování různých částí kódu podle jejich významu či automatické uzavírání uvozovek. -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 +V akci to uvidíme později. Brzy budeš na svůj editor kódu nahlížet jako na jeden ze svých oblíbených nástrojů. :) \ No newline at end of file diff --git a/cs/css/README.md b/cs/css/README.md index ab915ee6046..1f496afff78 100755 --- a/cs/css/README.md +++ b/cs/css/README.md @@ -1,114 +1,115 @@ -# CSS - aby byla tvoje aplikace krásná! +# CSS – make it pretty! 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 ;). +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. ;) -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 zdarma na internetu. Vymýšlet znovu, co již před námi někdo vymyslel, to by nebyla žádná legrace. +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. ## 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/ +Bootstrap is one of the most popular HTML and CSS frameworks for developing beautiful websites: https://getbootstrap.com/ -Napsali ho programátoři, kteří pracovali pro Twitter, a nyní ho vyvíjí dobrovolníci z celého světa. +It was written by programmers who worked for Twitter. Now it's developed by volunteers from all over the world! ## Instalace Bootstrapu -Chceš-li nainstalovat Bootstrap, je třeba přidat do `< head >` v souboru `.html` (`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 ``` -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. Hurá! - -![Obrázek 14.1][1] +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! - [1]: images/bootstrap1.png +![Obrázek 14.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 pro každého uživatele stejné. +Konečně se podíváme zblízka na téma, které jsme již zmínili, **statické soubory**. 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. ### 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`. +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`. Uděláš to tak, že vytvoříš složku s názvem `static` uvnitř aplikace blog: -``` -djangogirls -├── blog -│ ├── migrations -│ └── static -└── mysite -``` + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │   └── templates + └── mysite + -Django automaticky najde všechny složky s názvem "static" uvnitř vašich složek aplikací a bude moci využívat jejich obsah jako statické soubory. +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. ## Tvůj první soubor CSS! -Pokud chceš na webovou stránku přidat svůj vlastní styl, vytvoř css soubor. 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 -``` +Let's create a CSS file now, to add your own style to your web page. 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? -Čas napsat nějaké CSS! Otevři soubor `blog/static/css/blog.css` v editoru kódu. + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + -Nepůjdeme příliš hluboko do tématu přizpůsobení webu a učení o CSS, protože je to docela snadné a můžeš se o tom naučit více 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. +Čas k napsání nějakého CSS! Otevři soubor `blog/static/css/blog.css` v editoru kódu. - [2]: https://www.codecademy.com/tracks/web +We won't be going too deep into customizing and learning about CSS here. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. -Ale pojďme něco málo udělat. Co třeba 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 +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. 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/. Můžeš také použít [předdefinované barvy](http://www.w3schools.com/colors/colors_names.asp), `červená/red` a `zelená/green`. V souboru `blog/static/css/blog.css` přidej následující kód: +{% filename %}blog/static/css/blog.css{% endfilename %} + ```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 > odkaz < /a >< / h1 >`). V takovém případě sdělujeme, že barvu elementu měníme na `#FCA205`, což je oranžová. Samozřejmě sem můžeš vložit vlastní barvu! +`h1` je 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. 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`: +V CSS souboru určujeme styly pro prvky v souboru HTML. 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`. 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. 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 -``` +``` -Přečti si o [CSS selektorech ve w3schools][4]. +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). - [4]: http://www.w3schools.com/cssref/css_selectors.asp +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: -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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% load staticfiles %} -``` +``` + +We're just loading static files here. :) Between the `` and `` tags, after the links to the Bootstrap CSS files, add this line: -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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html ``` -Právě jsi řekla naší šabloně, kde je umístěn náš soubor CSS. +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 be overriden by code in Bootstrap files. Právě jsi řekla naší šabloně, kde je umístěn náš soubor CSS. Soubor by měl nyní vypadat takto: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html {% load staticfiles %} @@ -136,161 +137,168 @@ Soubor by měl nyní vypadat takto: OK, ulož soubor a aktualizuj stránky! -![Obrázek 14.2][5] +![Obrázek 14.2](images/color2.png) - [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! -Dobrá práce! Co kdybychom také chtěli provzdušnit náš web a zvětšit okraj na levé straně? Pojďme to zkusit! +{% filename %}blog/static/css/blog.css{% endfilename %} ```css body { padding-left: 15px; } -``` +``` -Přidej toto do svého CSS souboru, ulož soubor a koukni se, jak to funguje! +Add that to your CSS, save the file and see how it works! -![Obrázek 14.3][6] +![Obrázek 14.3](images/margin2.png) - [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`: -Možná můžeme také chtít přizpůsobit písmo v našem záhlaví. Vlož za tag `< head >` v souboru `blog/templates/blog/post_list.html`: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - -``` + +``` -Tento řádek bude importovat písmo s názvem *Lobster* z Google písem (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). -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: +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; font-family: 'Lobster'; } -``` - -![Obrázek 14.3][7] +``` - [7]: images/font.png +![Obrázek 14.3](images/font.png) Skvěle! -Jak jsme si řekli 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 zvlášť 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ě. +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. 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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html ``` -A nyní přidej třídu `post` do svého `div` obsahující blog post. +A nyní přidej třídu, `post` do svého `div` obsahující blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

+

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. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. Pro tuto chvíli stačí zkopírovat a vložit do souboru `blog/static/css/blog.css`: -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`: +{% filename %}blog/static/css/blog.css{% endfilename %} ```css .page-header { - background-color: #ff9400; - margin-top: 0; - padding: 20px 20px 20px 40px; + 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; + color: #ffffff; + font-size: 36pt; + text-decoration: none; } .content { - margin-left: 40px; + margin-left: 40px; } h1, h2, h3, h4 { - font-family: 'Lobster', cursive; + font-family: 'Lobster', cursive; } - .date { - float: right; - color: #828282; +.date { + color: #828282; } .save { - float: right; + float: right; } - .post-form textarea, .post-form input { - width: 100%; +.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; +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; } - .post { - margin-bottom: 70px; +.post { + margin-bottom: 70px; } - .post h1 a, .post h1 a:visited { - color: #000000; +.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: -Pak obklopující HTML kód, který zobrazuje příspěvek s deklaracemi tříd, nahraď tímto: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
+
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

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

{{ post.title }}

-

{{ post.text|linebreaksbr }}

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

published: {{ 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 +![Obrázek 14.4](images/final.png) -Woohoo! Vypadá to super, ne? Kód, který jsme vložili, opravdu není tak těžké pochopit. Měla bys být schopna pochopit většinu z něj jen jeho čtením. +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? -Neobávej se trochu poupravit CSS a pokusit se změnit některé věci. Když něco rozbiješ, můžeš to vždy vrátit zpět! +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! -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 díky CSS hezčí. +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. -Připravena na další kapitolu?! :) +Připravena na další kapitolu?! :) \ No newline at end of file diff --git a/cs/deploy/README.md b/cs/deploy/README.md index 380ebd21346..ac34738941f 100755 --- a/cs/deploy/README.md +++ b/cs/deploy/README.md @@ -1,317 +1,259 @@ # Nasazení! -> **Poznámka:** Projít následující kapitolu 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 to nestihneš teď. +> **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 si lidé konečně mohou prohlédnout tvou webovou aplikaci :). +Until now, your website was only available on your computer. Now you will learn how to deploy it! 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. +Jak jsi se dozvěděla, webové stránky musí být umístěny na serveru. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. - [1]: https://pythonanywhere.com/ +Další externí službu, kterou budeme používa je [GitHub](https://www.github.com), 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é! -Další externí službu, kterou budeme používat, je [GitHub][2], což je hostingová služba pro zdrojové kódy. Na internetu 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. +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. # 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 mocně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ář. +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. {% 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 jedno repo 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". +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:** Tečka na začátku názvu souboru je důležitá! Pokud budeš mít jakékoliv potíže s vytvořením (například Mac nerad vytváří soubory, které začínají tečkou, přes Finder), tak použij funkci "Uložit jako" v editoru, což je neprůstřelné. +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. Měla by jsi být ve složce `djangogirls`. -Je vhodné použít příkaz `git status` před použitím příkazu `git add`, anebo vždy, když si nejsi jistá, 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: +{% filename %}command-line{% endfilename %} -``` -$ git status - On branch master + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + - Initial commit +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). -Untracked files: - (use "git add ..." to include in what will be committed) - .gitignore - blog/ - manage.py - mysite/ +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: - nothing added to commit but untracked files present (use "git add" to track) -``` +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Poznámka:** Tečka na začátku názvu souboru je důležitá! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +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. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ 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 je to 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škrtlé, ponechej prázdnou možnost .gitignore (to už jsme udělaly 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 sis vybrat něco jiného, ale použijeme ho ještě mnohokrát později a musela bys ho pokaždé nahrazovat. Tak je zatím snazší se držet názvu `my-first-blog`. - -Na další obrazovce se zobrazí klon URL tvého repo. Zvol verzi "HTTPS", zkopíruj ji a za chvilku ji použijeme v terminálu: - -![][4] - - [4]: images/github_get_repo_url_screenshot.png +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Můžeš jít a mrknout se na to! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Pojďme natáhnout náš kód z GitHubu na PythonAnywhere vytvořením "klonu" našeho repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + -Teď potřebujeme spojit ú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 a heslo pro GitHub 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š se na něj jít podívat! 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 - -Jakmile se zaregistruješ 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. Zkontroluj to 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š na PythonAnywhere vytvořit virtualenv. 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. +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] 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 "yes" a pokračujeme! Také máš ráda, 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, pomocí příkazů `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! - -Běž 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 na to, abychom používali 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, čímž uložíš cestu předtím, než budeš pokračovat. - -> **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". +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. O statických souborech zjistíme trochu více později v tomto kurzu, až budeme upravovat CSS pro naše stránky. Klikni na **Save** a přejdi zpět na kartu **Web**. -Zvládly jsme to! Klikni na velké zelené tlačítko **Reload**, čímž zobrazíš svou aplikaci. Odkaz na to najdeš v horní části stránky. +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 zobrazit 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/ +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](https://www.pythonanywhere.com/web_app_setup/). Zkontroluj jestli tam nejsou nějaké chybové zprávy; nejnovější záznamy jsou na konci. Mezi běžné problémy patří: -* Často zapomínané kroky jsou ty, které jsme dělaly v konzoly: vytvoření virtualenv, aktivace, instalace Djanga, spuštění collectstatic, přenesení databáze. +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. -* Chyba k cestě virtualenv na kartě Web – bude obvykle označená malou červenou zprávou na stejném místě. +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. -* Chyba v konfiguračním souboru WSGI – máš cestu do složky my-first-blog v pořádku? +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? -* Vybrala jsi stejnou verzi Pythonu pro svůj virtualenv stejně jako pro svoji webovou aplikaci? Obe verze by měly být 3.4. +- Vybrala jsi stejnou verzi Pythonu pro svůj virtualenv stejně jako pro svoji webovou aplikaci? Obe verze by měly být 3.6. -* Existují některé [obecné tipy ladění na PythonAnywhere wiki][9]. +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). - [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError - -A pamatuj si, že tvůj kouč je tady, aby ti pomohl! +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. +The default page for your site should say "It worked!", just like it does on your local computer. 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. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? -Poplácej sama sebe *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 už teď! +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ď! \ No newline at end of file diff --git a/cs/deploy/install_git.md b/cs/deploy/install_git.md index 6cc2682b85d..51d68d31688 100755 --- a/cs/deploy/install_git.md +++ b/cs/deploy/install_git.md @@ -1,19 +1,52 @@ -### Windows +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ší. -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ý. +## Instalace Git -### MacOS + -Stáhni Git z [git-scm.com](https://git-scm.com/) a postupuj podle pokynů. +Git si můžeš stáhnout z [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Ostatní výchozí hodnoty jsou v pořádku. Odškrtni Windows-style konce řádků, pro commit je Unixový styl konce řádků správný. -### Linux +Do not forget to restart the command prompt or powershell after the installation finished successfully. -Pokud ho již nemáš nainstalovaný, git měl by být k dispozici pomocí Správce balíčků, zkus: + +Stáhni Git z [git-scm.com](https://git-scm.com/) a postupujte podle pokynů. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git ``` -sudo apt-get install git -# or -sudo yum install git -# or -sudo zypper install git + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git ``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/cs/deploy/signup_pythonanywhere.md b/cs/deploy/signup_pythonanywhere.md index fe6e67a8fe7..ca66bd0de69 100755 --- a/cs/deploy/signup_pythonanywhere.md +++ b/cs/deploy/signup_pythonanywhere.md @@ -1,5 +1,5 @@ -Dále je čas přihlásit se zdarma k účtu "Beginner" na PythonAnywhere. +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. - * [www.pythonanywhere.com](https://www.pythonanywhere.com/) +* [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. +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/cs/django/README.md b/cs/django/README.md index 3663ae96264..ec5bf1d2e49 100755 --- a/cs/django/README.md +++ b/cs/django/README.md @@ -1,27 +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. +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. 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. +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. +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. -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. +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. ## 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. +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. -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. +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. The web server reads the letter and then sends a response with a webpage. Ale když chceš něco poslat, musíš mít nějaký obsah. A Django je něco, 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*. +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *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! +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. +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Možná, že uživatel chtěl změnit něco v datech? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. -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čí. +Samozřejmě 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! +Takže místo studování přílišných podrobností, jednoduše začneme něco vytvářet pomocí Django a touto cestou se naučíme všechny důležité části! \ No newline at end of file diff --git a/cs/django_admin/README.md b/cs/django_admin/README.md index 7ddfc186a3e..1d4abd83791 100755 --- a/cs/django_admin/README.md +++ b/cs/django_admin/README.md @@ -1,49 +1,57 @@ # Django admin -Chceš-li přidávat, upravovat a mazat příspěvky, které jsme právě vymodelovaly, použijeme Django admin. +To add, edit and delete the posts we've just modeled, we will use Django admin. -Otevřeme soubor `blog/admin.py` a nahradíme jeho obsah následujícím kódem: +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} ```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)`. +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: +OK čas se podívat na náš Post model. Nezapomeň spustit `Pythonu manage.py runserver` v konzoli www serveru. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: -![Login page][1] +![Login page](images/login_page2.png) - [1]: images/login_page2.png +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. -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í): +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. -``` -(myvenv) ~/djangogirls$ python manage.py createsuperuser -Username: admin -Email address: admin@admin.com -Password: -Password (again): -Superuser created successfully. -``` +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + -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. +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): -![Django admin][2] + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + - [2]: images/django_admin3.png +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. -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 :). +![Django admin](images/django_admin3.png) -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é. +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) -![Django admin][3] +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. - [3]: images/edit_post3.png +![Django admin](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/ +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/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! +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/cs/django_forms/README.md b/cs/django_forms/README.md index f70ecd1a30d..0e9c24d7935 100755 --- a/cs/django_forms/README.md +++ b/cs/django_forms/README.md @@ -1,222 +1,248 @@ # 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! +Poslední věc, kterou chceme udělat na našich webových stránkách, je vytvořit příjemný způsob, jak přidávat a upravovat příspěvky na blogu. Django `admin` je super, ale je to dost těžko přizpůsobitelné a upravitelné do hezčí podoby. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! 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`. +Stejně jako všechny důležité části Djanga, formuláře mají své vlastní soubory: `forms.py`. -V našem adresáři potřebujeme vytvořit soubor s názvem `blog`. +Potřebujeme vytvořit soubor s tímto názvem v našem adresáři `blog`. -``` -blog - └── forms.py -``` + blog + └── forms.py + + +OK, let's open it and type the following code: -OK, otevři ho a zadej následující kód: +{% filename %}blog/forms.py{% endfilename %} ```python - from django import forms +from django import forms + +from .models import Post - from .models import Post +class PostForm(forms.ModelForm): - class PostForm(forms.ModelForm): - class Meta: - model = Post - fields = ('title', 'text',) -``` + 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`). +Musíme nejdříve importovat Django formuláře (`z 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`. +`PostForm`, jak asi předpokládáš, je jméno našeho formuláře. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. -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`). +Dále zde máme `třídu Meta`, kde řekneme Djangu, který model by měl být použít 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). +Nakonec můžeme Djangu říct co se má stát s jednotlivými poli našeho formuláře. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? -A je to! Vše, co teď musíme udělat, je použít formulář ve *view* a zobrazit ho v šabloně. +A je to! Vše, co 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. +So once again we will create a link to the page, a URL, a view and a template. ## 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`: +Je tedy čas k otevření souboru `blog/templates/blog/base.html`. Přidáme odkaz do `div` s názvem `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html -``` +``` -Všimni si, že chceme zavolat náš nový view `post_new`. +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. -Po přidání řádku by měl tvůj html soubor vypadat takto: +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% load staticfiles %} - - Django Girls blog - - - - - - - -
-
-
- {% block content %} - {% endblock %} -
-
-
- + + 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. +Po uložení a obnovení stránky http://127.0.0.1:8000 patrně uvidíš známou `NoReverseMatch` chybu, dobrá? ## URL Otevři `blog/urls.py` a přidej řádek: +{% filename %}blog/urls.py{% endfilename %} + ```python url(r'^post/new/$', views.post_new, name='post_new'), -``` +``` + +A výsledný kód bude vypadat takto: -Výsledný kód bude vypadat takto: +{% filename %}blog/urls.py{% endfilename %} ```python - from django.conf.urls import url - from . import views +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'), + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', 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ď. +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. ## post_new view Musíme otevřít soubor `blog/views.py` a přidat následující řádky: +{% filename %}blog/views.py{% endfilename %} + ```python from .forms import PostForm -``` +``` -a náš *view*: +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) -``` + 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. +Chceš-li vytvořit nový formulář `Post`, musíš zavolat `PostForm()` a předat ho do šablony. We will go back to this *view*, but for now, let's quickly create a template for the form. ## Š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: +* We have to display the form. We can do that with (for example) {% 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>`. +* And finally, just after the opening `` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. Toto je velmi důležité, protože tak vytvoříme bezpečnější formulář! If you forget about this bit, Django will complain when you try to save the form: -![CSFR zakázaná stránka][1] +![CSFR zakázaná stránka](images/csrf2.png) - [1]: images/csrf2.png +OK, so let's see how the HTML in `post_edit.html` should look: -Pojďme se nyní podívat, jak by mělo vypadat HTML v `post_edit.html`: +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} ```html {% extends 'blog/base.html' %} {% block content %} -

New post

- {% csrf_token %} - {{ form.as_p }} - - +

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 +![Nový formulář](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? +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? -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? +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? 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: +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) -``` + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? Všechna pole z formuláře jsou nyní k dispozici v proměnné `request.POST`. Neměla by jsi přejmenovávat `POST` na něco jiného (jediná další platná hodnota proměnné `method` je `GET`, ale nyní nemáme čas vysvětlovat rozdíly). -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). +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. Takže musíme přidat podmínku (použijeme na to `-if`): -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`). +{% filename %}blog/views.py{% endfilename %} ```python if request.method == "POST": - [...] + [...] else: - form = PostForm() -``` + 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: +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} ```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()`. +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. Zkontrolujeme, je-li formulář platný, a pokud ano, můžeme ho uložit! +{% filename %}blog/views.py{% endfilename %} + ```python if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.published_date = timezone.now() - post.save() -``` + 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` v a toto pole je požadováno). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! -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! +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: -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: +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import redirect -``` +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": -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. +{% filename %}blog/views.py{% endfilename %} ```python return redirect('post_detail', pk=post.pk) -``` +``` + +`post_detail` is the name of the view we want to go to. Pamatuj si, že tento *view* vyžaduje proměnnou `pk`. To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! -`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! +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? -Už jsme si toho řekly hodně, ale pravděpodobně chceš vidět, jak nyní celý *view* vypadá nyní, nemám pravdu? +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): @@ -231,165 +257,191 @@ def post_new(request): 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í**. +Pojďme se podívat, jestli to funguje. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! -## Ověření formuláře +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. -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á. +To je úžasné! -Pokus se uložit formulář bez `nadpisu` a `textu`. Hádej, co se stane! +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. 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!** kapitola za hlavním tutorialem. -![Ověření formuláře][3] +![Chyba přihlášení](images/post_create_error.png) - [3]: images/form_validation2.png +## Ověření formuláře -Django se stará o ověřování, že všechna pole v našem formuláři jsou správně. Není to skvělé? +A teď ti ukážeme jak cool jsou formuláře v Djangu. Blog příspěvek musí mít `title` a `text` pole. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. -> 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. +Try to save the form without `title` and `text`. Guess what will happen! -![Chyba přihlášení][4] +![Ověření formuláře](images/form_validation2.png) - [4]: images/post_create_error.png +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? ## 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). +Teď víme, jak přidat nový formulář. Ale co když chceme upravit stávající? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line -Otevři `blog/templates/blog/post_detail.html` a přidej následující řádek: +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html -``` +``` -tak, aby šablona vypadala takto: +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html {% extends 'blog/base.html' %} + {% block content %} -
- {% if post.published_date %} -
- {{ post.published_date }} -
- {% endif %} - -

{{ post.title }}

-

{{ post.text|linebreaksbr }}

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
{% endblock %} -``` +``` V `blog/urls.py` přidej tento řádek: +{% filename %}blog/urls.py{% endfilename %} + ```python - url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), -``` + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` -Znovu použijeme šablonu `blog/templates/blog/post_edit.html`, takže jediné, co chybí, je *view*. +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: +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} ```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ář: + 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}) +``` + +Vypadá to téměř úplně stejně jako náš view `post_new`? Ale ne zcela. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} ```python form = PostForm(request.POST, instance=post) -``` +``` + +…and when we've just opened a form with this post to edit: -a když jsme otevřely formulář s tímto příspěvkem pro úpravu: +{% filename %}blog/views.py{% endfilename %} ```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] +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: - [5]: images/edit_button2.png +![Tlačítko Upravit](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 +![Upravit formulář](images/edit_form2.png) -Neboj se změnit název nebo text a ulož změny! +Feel free to change the title or the text and save the changes! -Blahopřejeme! Tvoje aplikace je skoro kompletní! +Blahopřejeme! Tvoje aplikace je čím dál více 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/ +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/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. +Být schopna vytvářet nové příspěvky pouhým klepnutím na odkaz je super! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. -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: +V `blog/templates/blog/base.html` najdeš naši `page-header` `div` a kotevní tag, který jsme tam dali dříve. Řádek by měl vypadat nějak takto: + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html -``` +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Změň tag `< a >`, aby vypadal takto: -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: +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% if user.is_authenticated %} - + {% endif %} -``` +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. 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. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: -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. +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` -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! +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! ## 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 +* 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 -``` +{% filename %}command-line{% endfilename %} -* Pak v [Bash konzoli PythonAnywhere][7]: + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + - [7]: https://www.pythonanywhere.com/consoles/ +* Pak v [Bash konzoli PythonAnywhere](https://www.pythonanywhere.com/consoles/): -``` -$ cd my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic -[...] -``` +{% filename %}command-line{% endfilename %} -* Nakonec skoč na [kartu Web][8] a klikni na **Reload**. + $ cd my-first-blog + $ git pull + [...] + - [8]: https://www.pythonanywhere.com/web_app_setup/ +* Nakonec, skoč na [kartu Web](https://www.pythonanywhere.com/web_app_setup/) a klikni na **Reload**. -A mělo by to být! Gratulujeme :) +A mělo by to být! Gratulujeme :) \ No newline at end of file diff --git a/cs/django_installation/README.md b/cs/django_installation/README.md index 1c0841641c6..df771f1898d 100755 --- a/cs/django_installation/README.md +++ b/cs/django_installation/README.md @@ -1,5 +1,7 @@ # Instalace Django -> **Poznámka:** Pokud ses již propracovala přes kroky instalace - můžeš jít rovnou na další kapitolu! +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! -{% include "/django_installation/instructions.md" %} +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/cs/django_installation/instructions.md b/cs/django_installation/instructions.md index e8d4352485e..88dc01c000a 100755 --- a/cs/django_installation/instructions.md +++ b/cs/django_installation/instructions.md @@ -1,99 +1,150 @@ -> Čá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. +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. 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? +Takže pojď 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). +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ář. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. Pro tento kurz budeme používat nový adresář `djangogirls` vytvořený v domovském adresáři: -``` -mkdir djangogirls -cd djangogirls -``` +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + Vytvoříme virtualenv, s názvem `myvenv`. Obecný příkaz bude vypadat takto: -``` -python3 -m venv myvenv -``` +{% filename %}command-line{% endfilename %} + + $ Python3 -m venv myvenv + + + -### Windows +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: -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: +{% filename %}command-line{% endfilename %} -``` -C:\Users\Name\djangogirls > C:\Python34\python -m venv myvenv -``` + C:\Users\Name\djangogirls> 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! +Where `myvenv` is the name of your `virtualenv`. Můžeš použít i jiné jméno, ale používej malá písmena a nepoužívej mezery, diakritiku nebo speciální znaky. It is also good idea to keep the name short – you'll be referencing it a lot! -### 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 -``` +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: -`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! +{% filename %}command-line{% endfilename %} -> **POZNÁMKA:** Vytvoření virtuálního prostředí na Ubuntu 14.04, v současné době vyhazuje následující chybu: -> + $ 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. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> > 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 +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv > + + ## 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 -``` +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + -#### Linux a OS X + Spusť virtuální prostředí: -``` -~/djangogirls$ source myvenv/bin/activate -``` +{% filename %}command-line{% endfilename %} + + $ 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 +> +> {% filename %}command-line{% endfilename %} +> +> $ . 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í! +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. 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`. @@ -101,22 +152,50 @@ OK máme všechny důležité závislosti na místě a konečně můžeme nainst ## 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: `==`). +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. -``` -(myvenv) ~$ pip install django==1.8 -Downloading/unpacking django==1.8 -Installing collected packages: django -Successfully installed django -Cleaning up... -``` +{% filename %}command-line{% endfilename %} -v systému Windows + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + -> 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 +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + > 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! + + +A je to! Teď jsi (konečně) připravena k vytvoření aplikace Django! \ No newline at end of file diff --git a/cs/django_models/README.md b/cs/django_models/README.md index 44977a6ed93..99eff380670 100755 --- a/cs/django_models/README.md +++ b/cs/django_models/README.md @@ -1,113 +1,122 @@ # 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`. +Nyní chceme vytvořit něco, co bude ukládat všechny příspěvky na našem blogu. Ale aby jsme to mohli 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. +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. 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á). +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). -`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ť`). +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). -``` -Cat --------- -color -age -mood -owner -purr() -scratch() -feed(cat_food) - - -CatFood --------- -taste -``` + 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? +Jak tedy bude vypadat model blogu? Chceme vytvořit blog, ne? 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. +Určitě budeme v naše blogu potřebovat nějaký text s jeho obsahem a titulkem, že? It would be also nice to know who wrote it – so we need an author. Nakonec také chceme vědět, kdy byl příspěvek vytvořen a publikován. -``` -Post --------- -title -text -author -created_date -published_date -``` + 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. +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, že ano? 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! +Vzhledem k tomu, že už víme, co chceme dosáhnout, můžeme začít modelování v Django! ## 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. +Nyní víme jaký objekt chceme vytvořit, tak 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. +A model in Django is a special kind of object – it is saved in the `database`. Databáze je soubor dat. Je to místo, ve kterém 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. This is the default Django database adapter – it'll be enough for us right now. 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): +Abychom udrželi 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 -``` +{% filename %}Mac OS X and Linux:{% endfilename %} -Zjistíš, že nový adresář `blog` nyní obsahuje řadu souborů. Adresáře a soubory v našem projektu by měly vypadat následovně: + (myvenv) ~/djangogirls$ python manage.py startapp 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 -``` - -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: +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} ```python -INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'blog', -) -``` +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. +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: -Otevři `blog/models.py`, odstraň vše, co v něm je, a vlož následující kód: +{% filename %}blog/models.py{% endfilename %} ```python from django.db import models @@ -115,7 +124,7 @@ from django.utils import timezone class Post(models.Model): - author = models.ForeignKey('auth.User') + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) title = models.CharField(max_length=200) text = models.TextField() created_date = models.DateTimeField( @@ -131,53 +140,60 @@ class Post(models.Model): 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"). +> Double-check that you use two underscore characters (`_`) on each side of `str`. Tato konvence se v Pythonu používá často. Někdy je také nazýváme "dunder" (zktratka pro "Double-UNDERscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! -Vypadá to děsivě, že? Ale žádný strach, vysvětlíme ti, co tyto řádky znamenají! +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. -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):` – this line defines our model (it is an `object`). -`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` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models. Model` znamená, že Post je Django Model, takže Django ví, že by to mělo být uloženo v databázi. -* `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. +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) -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` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. -* `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. +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). -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). +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. -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`. +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. -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. +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. -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é! +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! ### 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: +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: -``` -(myvenv) ~/djangogirls$ python manage.py makemigrations blog -Migrations for 'blog': - 0001_initial.py: - - Create model Post -``` +{% filename %}command-line{% endfilename %} -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 makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + -``` -(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! +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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 + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/cs/django_orm/README.md b/cs/django_orm/README.md index 5f8e383fea2..eabef7672a2 100755 --- a/cs/django_orm/README.md +++ b/cs/django_orm/README.md @@ -1,180 +1,218 @@ # 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! +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. +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. -Je snazší naučit se to na příkladu. Pojďme to zkusit. +Je snazší naučit se to na příkladu. Pojďme to zkusit, můžeme? ## Django shell -Otevři svou lokální konzoli (ne na Python Anywhere) a napiš tento příkaz: +Otevři svou lokání konzoli (ne na Python Anywhere) a napiš tento příkaz: -``` -(myvenv) ~/djangogirls$ python manage.py shell -``` +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + Mělo by to mít takovýto efekt: -``` +{% filename %}command-line{% endfilename %} + +```python (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. +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. ### 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: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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! +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! -``` +{% filename %}command-line{% endfilename %} + +```python >>> from blog.models import Post -``` +``` -Tohle je jednoduché: importujeme model `Post` z `blog.models`. Pojďme znovu zkusit zobrazit všechny příspěvky: +We import the model `Post` from `blog.models`. Let's try displaying all posts again: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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? +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? ### Vytvoř objekt Takhle vytvoříš nový Post objekt v databázi: +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=ja, title='titulek', text='Test') ``` ->>> 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? +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? Nejdříve pojďme importovat User model: -``` +{% filename %}command-line{% endfilename %} + +```python >>> from django.contrib.auth.models import User -``` +``` Jaké uživatele máme v naší databázi? Zkus tohle: -``` +{% filename %}command-line{% endfilename %} + +```python >>> User.objects.all() ]> -``` +``` + +This is the superuser we created earlier! Let's get an instance of the user now: -Tohle je superuser, kterého jsme vytvořily dříve! Pojďme si teď vzít instanci tohoto uživatele: +{% filename %}command-line{% endfilename %} ```python -me = User.objects.get(username='ola') +>>> 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. +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. Teď můžeme konečně vytvořit příspěvek: +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=ja, title='titulek', text='Test') ``` ->>> Post.objects.create(author=me, title='titulek', text='Test') -``` -Hurá! Chceš se podívat, jestli to fungovalo? +Hurá! Chceš se podívat jestli to fungovalo? -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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. +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. ### 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: +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. V `Post.objects.all()` použijeme `filter` místo `all`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Teď náš kus kódu vypadá takhle: -``` +{% filename %}command-line{% endfilename %} + +```python >>> Post.objects.filter(author=ja) [, , , ] -``` +``` -Nebo možná chceme vidět všechny příspěvky, jež mají slovo 'titulek' v poli `title`? +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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". +> **Poznámka** Mezi `title` a `contains` jsou dvě podtržítka (`_`). Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "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: +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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: +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: -``` +{% filename %}command-line{% endfilename %} + +```python >>> post = Post.objects.get(title="Sample title") -``` +``` -A ten publikujeme pomocí naší metody `publish`! +A ten publikujeme pomocí naší metody `publish`: -``` +{% filename %}command-line{% endfilename %} + +```python >>> post.publish() -``` +``` -Teď se znovu pokus získat seznam publikovaných příspěvků (3krát zmáčkni šipku nahoru a zmáčkni `enter`): +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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`): -``` +{% filename %}command-line{% endfilename %} + +```python >>> Post.objects.order_by('created_date') [, , , ] -``` +``` Můžeme je také seřadit obráceně přidáním `-` na začátek: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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') -``` + >>> 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. +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: +Cool! Teď jsi připravená na další část! Pro zavření shell konzoli zadej toto: -``` +{% filename %}command-line{% endfilename %} + +```python >>> exit() $ -``` +``` \ No newline at end of file diff --git a/cs/django_start_project/README.md b/cs/django_start_project/README.md index 89cab58e432..16a51ff3bc0 100755 --- a/cs/django_start_project/README.md +++ b/cs/django_start_project/README.md @@ -1,84 +1,123 @@ # 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. +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Ochranou známku pro Django-marcador drží Markus Zapke-Gründemann et al. - [1]: http://django-marcador.keimlink.de/ +We're going to create a small blog! -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 Django, které vytvoří kostru Django projektu pro tebe. To je jen halda adresářů a souborů, které budeme později používat. -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 by jsi 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, aby jsme mohli najít důležité věci. -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. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. Jak se to dělá jsme vysvětlili v kapitole **Django instalace** v části **práce s virtualenv**. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. -> 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**: +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** -``` -(myvenv) ~/djangogirls$ django-admin startproject mysite . -``` +{% filename %}command-line{% endfilename %} -V systému Windows; **nezapomeň přidat tečku `.` na konci**: + (myvenv) ~/djangogirls$ django-admin startproject mysite . + -``` -(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). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} -> 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. + (myvenv) C:\Users\Name\djangogirls> django-admin.exe 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). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + `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 -``` + 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. +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. 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`. +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! +Prozatím budeme ignorovat ostatní soubory - nechceme v nich nic měnit. Jediná věc, kterou nezapomeň, žá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`) +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +Bylo by hezké mít správný čas na našich stránkách. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). - [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: -V settings.py najdi řádek, který obsahuje `TIME_ZONE`, a uprav jej tak, aby obsahoval tvoje vlastní časové pásmo: +{% filename %}mysite/settings.py{% endfilename %} ```python -TIME_ZONE = 'Europe/Prague' -``` +TIME_ZONE = 'Europe/Berlin' +``` -Uprav "Europe/Prague" podle potřeby. +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). -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`: +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} ```python STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') -``` +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} -## Nastavení databáze +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database 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`: +{% filename %}mysite/settings.py{% endfilename %} + ```python DATABASES = { 'default': { @@ -86,58 +125,77 @@ DATABASES = { '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: +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 vidě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 `python manage.py runserver`: +{% filename %}command-line{% endfilename %} -``` -(myvenv) ~/djangogirls$ python manage.py runserver -``` + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +A máme hotovo! Čas spustit webový server a měla by jsi vidět naše fungující webové stránky! + +## Starting the web server + +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`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + 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 -``` +{% filename %}command-line{% endfilename %} -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: + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + -``` -http://127.0.0.1:8000/ -``` +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} -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. + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + Blahopřejeme! Právě jsi vytvořila svůj první web a spustila jej pomocí webového serveru! Není to super? -![Fungovalo to!][3] +![Fungovalo to!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. - [3]: images/it_worked2.png +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). -Připravena pro další krok? Je tu čas k vytvoření nějakého obsahu! +Připravena pro další krok? Je tu čas k vytvoření nějakého obsahu! \ No newline at end of file diff --git a/cs/django_templates/README.md b/cs/django_templates/README.md index 187fa29351d..fa3aaaefd44 100755 --- a/cs/django_templates/README.md +++ b/cs/django_templates/README.md @@ -1,50 +1,54 @@ # Django šablony -Je čas zobrazit nějaká data! Django nám k tomuto účelu poskytuje užitečné vestavěné **šablonové tagy**. +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ší. +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. -**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. +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! ## 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 předchozí kapitole jsme dali 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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```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] +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, abys viděla výsledek: - [1]: images/step1.png +![Figure 13.1](images/step1.png) Jak vidíš, dostali jsme toto: -``` +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html , ]> -``` +``` 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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html {% for post in posts %} {{ post }} {% endfor %} -``` +``` Zkus udělat tohle ve své šabloně. -![Figure 13.2][2] +![Figure 13.2](images/step2.png) - [2]: images/step2.png +Funguje to! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. Můžeš smíchat HTML tagy se šablonovými. Naše `body` bude vypadat takhle: -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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html
@@ -58,51 +62,45 @@ Funguje to! Ale chceme, aby se zobrazovaly jako ty statické příspěvky, kter

{{ 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] +{% raw %}Všechno co dáš mezi `{% for %}` a `{% endfor %}` se zopakuje pro každý objekt v seznamu. Obnov svou stránku:{% endraw %} - [3]: images/step3.png +![Figure 13.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. +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? Přistupujeme k datům v každém poli defnovaném v našem `Post` modelu. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. ## 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... +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… -* Nejdřív hoď svůj kód na Github +* 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: +{% filename %}command-line{% endfilename %} - [4]: https://www.pythonanywhere.com/consoles/ + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + -``` -$ cd my-first-blog -$ git pull -[...] -``` +* Pak se přihlaš do [PythonAnywhere](https://www.pythonanywhere.com/consoles/) s jdi do **Bash konzole** (nebo vytvoř novou) a zadej: -* Nakonec jdi na záložku [Web][5] a klikni na **Reload**. Tvá stránka by měla být aktuální! +{% filename %}PythonAnywhere command-line{% endfilename %} - [5]: https://www.pythonanywhere.com/web_app_setup/ + $ cd my-first-blog + $ git pull + [...] + -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í. +* Konečně, jdi na záložku [Web](https://www.pythonanywhere.com/web_app_setup/) a klikni na **Reload**. Tvá stránka by měla být aktuální! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. Databáze v místním počítači a Python Anywhere není synchronizována. -Funguje to dokonale? Jsme hrdí! Odpočiň si na chvíli od počítače, zasloužíš si přestávku :) +Gratulujeme! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. -![Figure 13.4][6] +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) - [6]: images/donut.png +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/cs/django_urls/README.md b/cs/django_urls/README.md index 456b3d95a5b..7efc203025c 100755 --- a/cs/django_urls/README.md +++ b/cs/django_urls/README.md @@ -1,126 +1,129 @@ -# Django URL +# Django URLs -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. +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. ## 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): +Adresa URL je jednoduše webová adresa. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` je adresa URL! And `https://djangogirls.org` is also a URL.) -![Url][1] +![Url](images/url.png) - [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. +Každá stránka na internetu potřebuje svou vlastní URL. This way your application knows what it should show to a user who opens that URL. V Djangu používáme takzvaný `URLconf` (URL konfigurace). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct 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á: +Pojďme otevřít `mysite/urls.py` soubor v tvém zvoleném editoru kódu a uvidíme, jak vypadá: + +{% filename %}mysite/urls.py{% endfilename %} ```python -from django.conf.urls import include, url +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import 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(r'^admin/', admin.site.urls), ] -``` +``` + +As you can see, Django has already put something here for us. -Jak vidíš, Django už má tady něco pro nás připravené. +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. -Řá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? +The admin URL, which you visited in previous chapter, is already here: -Admin URL, které jsi navštívila v předchozí kapitole, už je tady: +{% filename %}mysite/urls.py{% endfilename %} ```python - url(r'^admin/', include(admin.site.urls)), -``` + url(r'^admin/', 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šší. +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. ## 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í. +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ě: +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: -``` -^ 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 -``` +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern -Cokoliv jiného v definici URL budeme brát doslovně. +Anything else in the URL definition will be taken literally. -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. +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. -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: +Psaní oddělených views pro všechna čísla příspěvků by bylo opravdu otravné. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: -* **^ 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 +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** znamená, že bude následovat číslo (jedeno 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! +## Your first 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ů. +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. -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`. +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. -Odstraň zakomentované řádky (řádky začínající `#`) a přidej řádek, který bude importovat `blog.urls` do hlavní URL('').`''`). +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. Tvůj `Mysite/urls.py` soubor by měl nyní vypadat takto: +{% filename %}mysite/urls.py{% endfilename %} + ```python -from django.conf.urls import include, url +from django.conf.urls import include +from django.conf.urls import url from django.contrib import admin urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), - url(r'', include('blog.urls')), + url(r'^admin/', 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. +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. +Writing regular expressions in Python is always done with `r` in front of the string. 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: +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} ```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). +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) Poté můžeme přidat náš první URL vzor: +{% filename %}blog/urls.py{% endfilename %} + ```python urlpatterns = [ - url(r'^$', views.post_list, name='post_list'), + 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. +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. 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 adresu' http://127.0.0.1:8000 /'. -![Error][2] +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. Název URL může být stejný jako název view, ale také může být úplně jiný. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. - [2]: images/error1.png +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. -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é: +![Error](images/error1.png) -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. +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. -> 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/ +> Pokud chceš vědět více o Django URLconfs, podívej se na oficiální dokumentaci: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/cs/django_views/README.md b/cs/django_views/README.md index 18d8e531d5a..5a7f88ef507 100755 --- a/cs/django_views/README.md +++ b/cs/django_views/README.md @@ -1,38 +1,44 @@ -# Django views – je čas začít tvořit! +# Django views – time to create! -Nejdříve se musíme zbavit chyb, které jsme vytvořily v předchozí kapitole :) +Nejdříve se musíme zbavit chyb, které jsme vytvořili 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* 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. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. 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: +OK, pojďme otevřít tento soubor a podívat se co tam je: + +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render # Create your views here. -``` +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. -Zatím zde není příliš informací. Nejjednodušší *view* může vypadat následovně. +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} ```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`. +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `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í. +Save the file, go to http://127.0.0.1:8000/ and see what we've got. Další chyba! Přečti si, co je špatně nyní: -![Error][1] - - [1]: images/error.png +![Error](images/error.png) -Je to jednoduché: *TemplateDoesNotExist*. Musíme opravit tuto chybu a v následující kapitole vytvořit šablonu! +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! -> Další informace ohledně Django views získáš v oficiální dokumentaci na: https://docs.djangoproject.com/en/1.8/topics/http/views/ +> Další informace ohledně Django views získáš v oficiální dokumentaci na: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/cs/dynamic_data_in_templates/README.md b/cs/dynamic_data_in_templates/README.md index a75c2805c2e..6bc6323d13a 100755 --- a/cs/dynamic_data_in_templates/README.md +++ b/cs/dynamic_data_in_templates/README.md @@ -1,44 +1,50 @@ # 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ě? +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ě? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? -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ě. +To je přesně to, co *views* mají dělat: spojovat modely a šablony. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. -OK, tak jak toho dosáhneme? +OK, so how will we achieve this? Potřebujeme otevřít `blog/views.py`. Prozatím `post_list` *view* vypadá takhle: +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render def post_list(request): return render(request, 'blog/post_list.html', {}) -``` +``` + +Vzpomínáš si, jak jsme mluvili o zahrnování kódu napsaného v různých souborech? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: -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`: +{% filename %}blog/views.py{% endfilename %} ```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`). +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.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`. +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. ## QuerySet -Už bys měla mít povědomí o tom, jak QuerySety fungují. To jsme probraly v kapitole [Django ORM (QuerySets)][1]. +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). - [1]: ../django_orm/README.md +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! -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! +{% filename %}blog/views.py{% endfilename %} ```python Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') -``` +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: -Teď tento kousek kódu vložíme do souboru `blog/views.py` do funkce `def post_list(request)`: +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render @@ -48,18 +54,18 @@ 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. +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. -Kód také používá funkci `timezone.now()`, takže potřebujeme přidat import pro `timezone`. +Vezmi, prosím, na vědomí, že jsme vytvořili *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. -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 `''`. +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. Potřebujeme je pojmenovat (teď zůstaneme u `'posts'`). :) Mělo by to vypadat takhle: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. A nakonec by náš `blog/views.py` soubor měl vypadat takhle: +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render from django.utils import timezone @@ -68,8 +74,8 @@ 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/ +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/cs/extend_your_application/README.md b/cs/extend_your_application/README.md index 55c33681cff..b9917a4fd4d 100755 --- a/cs/extend_your_application/README.md +++ b/cs/extend_your_application/README.md @@ -1,16 +1,16 @@ # 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é. +Dokončili 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? +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: +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -26,117 +26,124 @@ Začneme s přidáním odkazu do `blog/templates/blog/post_list.html` souboru. Z {% endfor %} {% endblock %} -``` - +``` {% 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 %} +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```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 %} +{% 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*. +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail -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: +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! -![NoReverseMatch error][1] +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: - [1]: images/no_reverse_match2.png +![NoReverseMatch error](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/ +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. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. Tento soubor by měl vypadat takto: -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: +{% filename %}blog/urls.py{% endfilename %} ```python - from django.conf.urls import url - from . import views +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! + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` -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*. +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: -`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]+)`. +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. 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`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` znamená, že je zde má být jedna nebo více číslic. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! -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! +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*. -![AttributeError][2] +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! - [2]: images/attribute_error2.png +![AttributeError](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! +This time our *view* is given an extra parameter, `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: +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} ```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! +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! -![DoesNotExist error][3] +![DoesNotExist error](images/does_not_exist2.png) - [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`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. -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](images/404_2.png) -![Page not found][4] +Dobrou zprávou je, že můžeš skutečně vytvořit vlastní stránku, `Page Not Found 404` a udělat jí tak krásnou, jak jen chceš. Ale to není nyní super důležité, takže to přeskočíme. - [4]: images/404_2.png +OK, time to add a *view* to our `views.py` file! -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. +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. -Ok, čas k přidání *view* do našeho souboru `views.py`! +We should open `blog/views.py` and add the following code near the other `from` lines: -Měla bys otevřít `blog/views.py` a přidat následující kód: +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render, get_object_or_404 -``` +``` + +And at the end of the file we will add our *view*: -Poblíž jiné řádky `from`. A na konec souboru přidáme náš *view*: +{% filename %}blog/views.py{% endfilename %} ```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 +![Post list view](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 +![TemplateDoesNotExist error](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. +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 +## Create a template for the post details Vytvoříme soubor `blog/templates/blog` s názvem `post_detail.html`. Celý příkaz bude vypadat takto: +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + ```html {% extends 'blog/base.html' %} @@ -151,47 +158,40 @@ Celý příkaz bude vypadat takto:

{{ 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 %} +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, že? -OK, teď můžeme aktualizovat naše stránky a uvidíš, jestli `Page Not Found` je pryč. +{% 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 %} -![Post detail page][7] +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. - [7]: images/post_detail2.png +![Post detail page](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. +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 -``` +{% filename %}command-line{% endfilename %} -* Pak v [Bash konzoli PythonAnywhere][8]: + $ 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 + - [8]: https://www.pythonanywhere.com/consoles/ +Pak v [Bash konzoli PythonAnywhere](https://www.pythonanywhere.com/consoles/): -``` -$ cd my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic -[...] -``` +{% filename %}command-line{% endfilename %} -* Nakonec jdi na [kartu Web][9] a klikni na **Reload**. + $ cd my-first-blog + $ git pull + [...] + - [9]: https://www.pythonanywhere.com/web_app_setup/ +Nakonec, skoč na [kartu Web](https://www.pythonanywhere.com/web_app_setup/) a klikni na **Reload**. -A mělo by to být! Gratulujeme :) +A mělo by to být! Gratulujeme :) \ No newline at end of file diff --git a/cs/how_the_internet_works/README.md b/cs/how_the_internet_works/README.md index 3543d4bd56a..6590f0434fc 100755 --- a/cs/how_the_internet_works/README.md +++ b/cs/how_the_internet_works/README.md @@ -1,53 +1,47 @@ # 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/). +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> This chapter is inspired by the talk "How the Internet works" by 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`? +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`? -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. +První věc, které potřebuješ 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á unikátními webové stránky: 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š. +Pokud je ti programování zcela cizí, z počátku pro tebe může být těžké pochopit HTML, 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, následovaly instrukce a prezentovaly 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. +Jako s každým souborem, 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. That's why they're called *servers* – because they *serve* you data. -OK, ale chceš vědět jak internet vypadá, že ano? +OK, but you want to know how the Internet looks, right? Nakreslili jsme pro tebe obrázek! Vypadá takhle: -![Figure 1.1][1] +![Figure 1.1](images/internet_1.png) - [1]: images/internet_1.png +Vypadá to jako pěkný bordel, že? In fact it is a network of connected machines (the above-mentioned *servers*). 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: -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](images/internet_3.png) -![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. +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. 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. 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!" +![Figure 1.3](images/internet_2.png) -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. +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!" -![Figure 1.4][4] +Tvůj dopis se pošle na tobě 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. - [4]: images/internet_4.png +![Figure 1.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ý! +That's how it works - 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! -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. +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. 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. -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). +When you send a letter, it needs to have certain features to be delivered correctly: an address, a stamp, etc. Také používáš jazyk kterému adresát rozumí, že ano? 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). +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ů :). +Since this is a Django tutorial, you might ask what Django does. 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! +Enough talk – time to create! \ No newline at end of file diff --git a/cs/html/README.md b/cs/html/README.md index 503feb1e10e..8e4f108c64e 100755 --- a/cs/html/README.md +++ b/cs/html/README.md @@ -1,74 +1,73 @@ # Úvod do HTML -Co je to šablona? +Co je to šablona, se ami ptáš? -Š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. +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. -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**). +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**). ## 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 is a code that is interpreted by your web browser – such as Chrome, Firefox or Safari – to display a web page for the user. -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). +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 representují **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. +Vytvoření šablony znamená vytvoření souboru šablony. Všechno je soubor, dobř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ší.) + blog + └───templates + └───blog + -A teď vytvoř soubor `post_list.html` uvnitř adresáře `blog/templates/blog`. Prozatím ho nech prázdný. +(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.) -Podívej se, jak tvá stránka vypadá teď: http://127.0.0.1:8000/ +A teď vytvoř soubor `post_list.html` (pro teď ho nech prázdný) uvnitř adresáře `blog/templates/blog`. -> 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`. +Podívej se jak tvá stránka vypadá teď: http://127.0.0.1:8000/ -![Figure 11.1][1] +> Pokud se ti stále zobrazuje chyba`TemplateDoesNotExists`, zkus restartovat server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. - [1]: images/step1.png +![Figure 11.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. +Žá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í: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html -

Ahoj!

-

Funguje to!

+

Hi there!

+

It works!

-``` - -Tak jak tvá stránka vypadá teď? Klikni a zjisti to: http://127.0.0.1:8000/ +``` -![Figure 11.2][2] +So how does your website look now? Visit it to find out: http://127.0.0.1:8000/ - [2]: images/step3.png +![Figure 11.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 +* The most basic tag, ``, is always the beginning of any web page and `` is always the end. 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 and body -## Head & body +Každá HTML stránka je také rozdělena na dva elementy: **head** (hlavu) a **body** (tělo. -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. -* **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. -* **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 sdělili co na té stránce skutečně je. -`` používáme, abychom prohlížeči sdělili konfiguraci stránky, ``, abychom řekli, co na té stránce skutečně je. +For example, you can put a web page title element inside the ``, like this: -Například dovnitř `` můžeš dát element title (titulek), třeba takhle: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html @@ -76,41 +75,42 @@ Například dovnitř `` můžeš dát element title (titulek), třeba takh Ola's blog -

Ahoj!

-

Funguje to!

+

Hi there!

+

It works!

-``` +``` Ulož soubor a načti znovu svou stránku. -![Figure 11.3][3] - - [3]: images/step4.png +![Figure 11.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ř). +Pravděpodobně jsi si 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: `

`. +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ě. +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. ## 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 +* `

A heading

` for your most important heading +* `

Pod-nadpis

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

A sub-sub-heading

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

A paragraph of text

` +* `text` zvýrazňuje tvůj text +* `text` hodně zvýrazňuje tvůj text +* `
` goes to another line (you can't put anything inside br and there's no closing tag) +* `link` vytváří odkaz +* `
  • První položka seznamu
  • second item
` vytváří seznam, zrovna jako tento! +* `
` definuje sekce stránky + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: -Zde je příklad celé šablony: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html @@ -119,98 +119,95 @@ Zde je příklad celé šablony:

published: 14.06.2014, 12:14

-

Můj první příspěvek

+

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

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.

+

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.

-``` +``` 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: +* The first `div` element contains the title of our blog – it's a heading and a link +* 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. -![Figure 11.4][4] +To nám dá následující efekt: - [4]: images/step6.png +![Figure 11.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**. +Jupííí! 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**. -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. +What we really want to do is display real posts added in our Django admin – and that's where we're going next. ## 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): +Bylo by fajn vidět všecho tohle venku a živé na internetu, že jo? Pojďme udělat další PythonAnywhere nasazení (deploy): -### Commitni a hoď svůj kód na Github +### Commitni, a pushni 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): +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 -``` +{% filename %}command-line{% endfilename %} + + $ 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 . -``` +{% filename %}command-line{% endfilename %} -> **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ář. + $ git add --all . + -Než nahrajeme všechny soubory, zkontrolujme, co bude `git` nahrávat (všechny soubory, které bude `git` nahrávat, se zobrazí zeleně): +> **Note** `--all` means that `git` will also recognize if you've deleted files (by default, it only recognizes new/modified files). Taky si vzpomeň (ze 3. kapitoly), že `.` znamená aktuální adresář. -``` -$ git status -``` +Než nahrajeme všechny soubory, zkontrolujme co bude `git` nahrávat (všechny soubory, které bude `git` nahrávat, se zobrazí zeleně): -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. +{% filename %}command-line{% endfilename %} -``` -$ git commit -m "Změněn HTML kód stránek." -``` + $ 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ěnili. 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. + +{% filename %}command-line{% endfilename %} + + $ 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: +Once we've done that, we upload (push) our changes up to GitHub: -``` -git push -``` +{% filename %}command-line{% endfilename %} -### Stáhni svůj nový kód na PythonAnywhere a načti webovou aplikaci + $ git push + -* Otevři [stránku s konzolí na PythonAnywhere][5] a jdi do své **Bash konzole** (nebo začni novou). Potom zadej: +### Stáhni svůj nový kód na PythonAnywhere a načti webovou aplikaci - [5]: https://www.pythonanywhere.com/consoles/ +* Otevři [stránku s konzolí na PythonAnywhere](https://www.pythonanywhere.com/consoles/) a jdi do své **Bash konzole** (nebo začni novou). Potom zadej: -``` -$ cd ~/my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic -[...] -``` +{% filename %}command-line{% endfilename %} -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. + $ cd ~/my-first-blog + $ git pull + [...] + -* A konečně, skoč na záložku [Web][6] a klikni na **Reload** (Znovu načíst). +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. - [6]: https://www.pythonanywhere.com/web_app_setup/ +* A konečně, skoč na záložku [Web](https://www.pythonanywhere.com/web_app_setup/) a klikni na **Reload** (Znovu načíst). -Tvůj update by měl běžet živě! Obnov svou stránku v prohlížeči. Měla bys vidět změny :) +Obnov svou stránku v prohlížeči. Měla bys vidět změny. :) \ No newline at end of file diff --git a/cs/install_git.md b/cs/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/cs/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/cs/installation/README.md b/cs/installation/README.md index cdd38b9c502..79212ff2974 100755 --- a/cs/installation/README.md +++ b/cs/installation/README.md @@ -1,16 +1,21 @@ # 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). +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. -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. +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ě. 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. -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. +If you find it useful, you can follow 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. 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. +Při workshopu budeme vytvářet blog a existuje zde několik nastavení, které se budou během kurzu hodit před tím než začneš programovat. + + {% include "/chromebook_setup/instructions.md" %} + + # Instalace Pythonu @@ -38,12 +43,16 @@ Přejděte na [GitHub.com](https://www.github.com) a vytvořte si zdarma uživat # 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: +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: + +* [Jak funguje internet](../how_the_internet_works/README.md) + +* [Úvod do příkazového řádku](../intro_to_command_line/README.md) - * [Jak funguje internet](../how_the_internet_works/README.md) +* [Úvod do Pythonu](../python_introduction/README.md) - * [Úvod do příkazového řádku](../intro_to_command_line/README.md) +* [Co je Django?](../django/README.md) - * [Úvod do Pythonu](../python_introduction/README.md) +# Enjoy the workshop! - * [Co je Django?](../django/README.md) +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. \ No newline at end of file diff --git a/cs/instructions.md b/cs/instructions.md new file mode 100644 index 00000000000..30bd493b11b --- /dev/null +++ b/cs/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/cs/intro_to_command_line/README.md b/cs/intro_to_command_line/README.md index 2bdd6c0f5de..65f6c62e7eb 100755 --- a/cs/intro_to_command_line/README.md +++ b/cs/intro_to_command_line/README.md @@ -1,127 +1,178 @@ # Ú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 :) +> 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! :) **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. +> **Note** Please note that throughout this book we use the terms 'directory' and 'folder' interchangeably but they are one and the same thing. ## 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*. +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. It's much like Windows Explorer or Finder on the Mac, but without the graphical interface. 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. +Chceš-li začít experimentovat je třeba nejprve otevřít naše rozhraní příkazové řádky. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + -### Windows + -Jdi na menu Start → Všechny programy → Příslušenství → Příkazová řádka. +Go to Applications → Utilities → Terminal. -### 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í, jen to vygoogli. :) -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: -``` -$ -``` +{% filename %}command-line{% endfilename %} + + $ + + + + + + +V systému Windows je to `>` tento znak: -V systému Windows je to tento znak `>`: +{% filename %}command-line{% endfilename %} -``` -> -``` + > + -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. +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. :) + +> 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. ## Tvůj první příkaz (hurá!) -Pojďme začít s něčím jednoduchým. Zadej tento příkaz: +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} -``` -$ whoami -``` + $ whoami + -nebo + -``` -> whoami -``` + + +{% filename %}command-line{% endfilename %} + + > whoami + + + A zmáčkni `enter`. Tohle je výsledek: -``` -$ whoami -olasitarska -``` +{% filename %}command-line{% endfilename %} -Jak vidíš, počítač právě vypsal tvé uživatelské jméno. Pěkný, co?:) + $ whoami + olasitarska + -> Zkus každý příkaz zadat, nekopíruj ho prostým vyjmout/vložit. Zapamatuješ si tak více! +Jak vidíš, počítač právě vypsal tvé uživatelské jméno. Pěkný, co? :) + +> Try to type each command; do not copy-paste. You'll remember more this way! ## 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? +Každý operační systém má mírně odlišnou sadu příkazů na příkazové řádce, ujisti se, ž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 -``` +{% filename %}command-line{% endfilename %} -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. + $ pwd + /Users/olasitarska + > Poznámka: 'pwd' je zkratka pro "print working directory / zobrazení cesty pro pracovní adresář". + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +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. + * * * ### Seznam souborů a adresářů -Tak co je v něm? Bylo by fajn zjistit, co je v našem adresáři. Podívejme se: +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... -``` +{% filename %}command-line{% endfilename %} -Windows: + $ ls + Aplikace + Desktop + Stažené soubory + Hudba... + -``` -> 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 %} + + > 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. * * * @@ -129,33 +180,49 @@ Directory of C:\Users\olasitarska Teď pojďme do adresáře plochy: -``` -$ cd Desktop -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ cd Desktop + -``` -> cd Desktop -``` + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + Zkontroluj, zda-li se adresář skutečně změnil: -``` -$ pwd -/Users/olasitarska/Desktop -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ pwd + /Users/olasitarska/Desktop + -``` -> cd -C:\Users\olasitarska\Desktop -``` + + + + +{% filename %}command-line{% endfilename %} + + > 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í. +> 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` key twice to get a list of options. * * * @@ -163,17 +230,25 @@ A je to! Co si vytvořit pokusnou složku na ploše? Můžeš to udělat tímto způsobem: -``` -$ mkdir pokus -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ mkdir pokus + -``` -> 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 :) + + +{% filename %}command-line{% endfilename %} + + > mkdir pokus + + + + +Tento malý příkaz vytvoří složku s názvem `pokus` na ploše. Jestli 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. @@ -181,25 +256,33 @@ Tento malý příkaz vytvoří složku s názvem `pokus` na ploše. Zda se na pl ### 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`. +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) #### Řešení: -``` -$ cd pokus -$ mkdir test -$ ls -test -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ cd pokus + $ mkdir test + $ ls + test + -``` -> cd pokus -> mkdir test -> dir -05/08/2014 07:28 PM test -``` + + + + +{% filename %}command-line{% endfilename %} + + > cd pokus + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + Gratulujeme! :) @@ -207,76 +290,116 @@ 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. +Nechceme si nechat nepořádek v počítači, takže musíme odstranit vše, co jsme až do tohoto okamžiku dělali. + +Zaprvé potřebujeme se dostat zpátky na plochu: -Za prvé se potřebujeme dostat zpátky na plochu: + -``` -$ cd .. -``` +{% filename %}command-line{% endfilename %} -Windows: + $ cd .. + -``` -> 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ář). + + +{% 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). Zkontroluj, kde se nacházíš: -``` -$ pwd -/Users/olasitarska/Desktop -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ pwd + /Users/olasitarska/Desktop + -``` -> cd -C:\Users\olasitarska\Desktop -``` + + + + +{% filename %}command-line{% endfilename %} + + > 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á. +> **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. + + -``` -$ rm -r pokus -``` +{% filename %}command-line{% endfilename %} -Windows: + $ rm -r pokus + -``` -> rmdir /S pokus -Are you sure ? Y -``` + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S pokus + Are you sure ? Y + + + Hotovo! Vše je skutečně odstraněno. Pojďme to zkontrolovat: -``` -$ ls -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ ls + -``` -> dir -``` + + + + +{% filename %}command-line{% endfilename %} + + > 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? :) +That's it for now! You can safely close the command line now. Let's do it the hacker way, alright? :) + + -``` -$ exit -``` +{% filename %}command-line{% endfilename %} -Windows: + $ exit + -``` -> exit -``` + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + Suprový, co? :) @@ -284,22 +407,22 @@ Suprový, co? :) 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** | +| Příkaz (Windows) | Příkaz (Mac OS / Linux) | Popis | Příklad | +| ----------------------- | ----------------------- | -------------------------- | ------------------------------------------------- | +| zavření příkazové řádky | zavření příkazové řádky | Zavřít okno | **zavření příkazové řádky** | +| cd | cd | změnit adresář | **cd test** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (or del) | rm | delete a file | **del c:\test\test.txt** | +| rmdir /S | rm -r | delete a directory | **rm -r testdirectory** | 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 +Pokud jsi zvědavá, na [ss64.com](http://ss64.com) je úplný přehled příkazů pro všechny operační systémy. -## Připravena? +## Připraveno? -Pojďme se ponořit do Pythonu! +Pojďme se ponořit do Pythonu! \ No newline at end of file diff --git a/cs/python_installation/README.md b/cs/python_installation/README.md index 42f150debad..e19dfa4dcd6 100755 --- a/cs/python_installation/README.md +++ b/cs/python_installation/README.md @@ -2,12 +2,14 @@ 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. +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ý! +Python vznikl na konci 80. let a jeho hlavním cílem je být čitelný lidským bytostem (nejen strojům!). This is why it looks simpler than other programming languages, but don't worry – Python is also really powerful! # 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! +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/cs/python_installation/instructions.md b/cs/python_installation/instructions.md index 52466b1d549..deae1aee6df 100755 --- a/cs/python_installation/instructions.md +++ b/cs/python_installation/instructions.md @@ -1,64 +1,106 @@ -> Tato podkapitola čerpá z Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) +> 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 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. +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.6, so if you have any earlier version, you will need to upgrade it. -### 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! +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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. -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": +One thing to watch out for: During the installation, you will notice a window marked "Setup". Make sure you tick the "Add Python 3.6 to PATH" checkbox and click on "Install Now", as shown here: -![Nezapomeň přidat Python do cesty](../python_installation/images/add_python_to_windows_path.png) +![Nezapomeň přidat Python do cesty](../python_installation/images/python-installation-options.png) -### Linux +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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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." + +Musíte jít na web https://www.python.org/downloads/release/python-361/ a stáhněte si instalátor Python: + +* Stáhni *Mac OS X 64-bit/32-bit installer* soubor, +* Double click *python-3.6.1-macosx10.6.pkg* to run the installer. + + + + 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 -``` +{% filename %}command-line{% endfilename %} -Pokud Python nemáš nainstalovaný nebo pokud chceš nainstalovat jinou verzi, můžeš postupovat takto: + $ python3 – version + Python 3.6.1 + -#### Debian nebo Ubuntu +If you have a different 'micro version' of Python installed, e.g. 3.6.0, then you don't have to upgrade. Pokud Python nemáš nainstalovaný, nebo pokud chceš nainstalovat jinou verzi, můžeš postupovat takto: -Použij tento příkaz v konzoli: + + + + +Zadej tento příkaz do konzole: + +{% filename %}command-line{% endfilename %} -``` -sudo apt-get install python3.4 -``` + $ sudo apt-get install python3.6 + -#### Fedora + + + Použij tento příkaz v konzoli: -``` -$ sudo dnf nainstalovat python3.4 -``` +{% filename %}command-line{% endfilename %} + + $ sudo dnf nainstalovat python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. -#### openSUSE + + + Použij tento příkaz v konzoli: -``` -$ sudo zypper install python3 -``` +{% filename %}command-line{% endfilename %} + + $ 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: +Verify the installation was successful by opening a command prompt and running the `python3` command: - * 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. +{% filename %}command-line{% endfilename %} -Ověř, zda instalace proběhla úspěšně, otevři aplikaci *Terminal* a spusť příkaz `python3`: + $ python3 – version + Python 3.6.1 + -``` -$ python3 – version -Python 3.4.2 -``` +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. * * * -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. +If you have any doubts, or if something went wrong and you have no idea what to do next, please ask your coach! Někdy se věci nevyvíjejí hladce a je lepší požádat o pomoc někoho s více zkušenostmi. \ No newline at end of file diff --git a/cs/python_introduction/README.md b/cs/python_introduction/README.md index 3448c09a381..5753f17b976 100755 --- a/cs/python_introduction/README.md +++ b/cs/python_introduction/README.md @@ -1,67 +1,87 @@ # Úvod do Pythonu -> Část této kapitoly je založena na kurzu Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> Part of this chapter is based on tutorials by 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]. +> 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. - [1]: ../intro_to_command_line/README.md +Chceš-li si začít hrát s Pythonem, musíme otevřít *příkazový řádek* v počítači. You should already know how to do that – you learned it in the [Intro to Command Line](../intro_to_command_line/README.md) chapter. 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`. +Chceme otevřít Python konzoli, tak 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. ->>> -``` +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.1 (...) + 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. +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. You don't have to type in `>>>` – Python will do that for you. 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`. +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. -``` ->>> 2 + 3 +{% filename %}command-line{% endfilename %} + +```python +>>> 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` +Nice! See how the answer popped out? Python knows math! You could try other commands like: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} -Chvíli si s tím hraj a pak se sem vrať zpátky :). +```python +>>> 2 ** 3 +8 +``` -Jak vidíš, Python je skvělá kalkulačka. Pokud tě zajímá, co jiného můžeš dělat... +Chvíli si s tím hraj a pak se sem vrať zpátky. :) + +As you can see, Python is a great calculator. If you're wondering what else you can do… ## Řetězce A co tvé jméno? Zadej své jméno do uvozovek, jak vidíš níže: -``` ->>> "Ola" +{% filename %}command-line{% endfilename %} + +```python +>>> "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. +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 to co je uvnitř, je řetězec. Řetězce mohou být spojovány. Zkus toto: -``` ->>> "Ahoj " + "Ola" +{% filename %}command-line{% endfilename %} + +```python +>>> "Ahoj" + "Ola" 'Ahoj Ola' ``` Také můžeš násobit řetězce s číslem: -``` ->>> "Ola" * 3 +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 'OlaOlaOla' ``` @@ -69,31 +89,39 @@ Pokud budeš chtít dát apostrof dovnitř svého řetězce, máš dvě možnost Pomocí dvojité uvozovky: -``` ->>> "Runnin' down the hill" +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" "Runnin' down the hill" ``` -nebo použít escape sekvenci - před apostrof napsat zpětné lomítko (\`): +nebo použít escape sekvenci - před apostrof napsat zpětné lomítko (``): -``` ->>> 'Runnin\' down the hill' +{% filename %}command-line{% endfilename %} + +```python +>>> '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() +{% filename %}command-line{% endfilename %} + +```python +>>> "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áš. +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. -Pokud chceš znát počet písmen ve svém jméně, tak pro to má Python také funkci! +If you want to know the number of letters contained in your name, there is a **function** for that too! -``` ->>> len("Ola") +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") 3 ``` @@ -101,12 +129,12 @@ Zajímá tě, proč někdy voláš funkce s `.` na konci řetězce (jako `"Ola". ### Shrnutí -OK, dost bylo řetězců. Co ses zatím naučila: +OK dost řetězců. Co jsi se 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ů. +- **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. To jsou základy každého programovacího jazyka. Připravena na něco dalšího? Vsadíme se, že ano! @@ -114,709 +142,896 @@ To jsou základy každého programovacího jazyka. Připravena na něco dalšíh 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 +{% filename %}command-line{% endfilename %} + +```python +>>> 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)) +{% filename %}command-line{% endfilename %} + +```python +>>> 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** +- 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')`? +> Important: we can convert numbers into text, but we can't necessarily convert text into numbers – what would `int('hello')` be anyway? ## 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. +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 jejich kód byl čitelnější a nemusejí si pamatovat co dané věci jsou. Řekněme, že chceme vytvořit novou proměnnou s názvem `name`: -``` +{% filename %}command-line{% endfilename %} + +```python >>> name = "Ola" ``` -Vidíš? Je to snadné! Jednoduše napíšeš: name se rovná Ola. +We type name equals 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`: +Jak jsi si jistě všimla, tvůj program nic nevrátil jako to dělal před tím. Jak tedy víme, že proměnná skutečně existuje? Jednoduše zadejte `name` a stiskni klávesu `Enter`: -``` ->>> name +{% filename %}command-line{% endfilename %} + +```python +>>> name 'Ola' ``` -Hurá! První proměnná :)! Kdykoli můžeš změnit to, na co daná proměnná ukazuje: +Yippee! Your first variable! :) You can always change what it refers to: -``` +{% filename %}command-line{% endfilename %} + +```python >>> name = "Sonja" ->>> name +>>> name 'Sonja' ``` Můžeš ji také použít ve funkcích: -``` ->>> len(name) +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) 5 ``` -Super, ne? Samozřejmě proměnná může obsahovat cokoliv, například také čísla! Zkus tohle: +Awesome, right? Of course, variables can be anything – numbers too! Try this: -``` ->>> a = 4 ->>> b = 6 ->>> a * b +{% filename %}command-line{% endfilename %} + +```python +>>> 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 +{% filename %}command-line{% endfilename %} + +```python +>>> 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ě. +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ě, zkontrolujte svůj kód, aby jsi zjistila jestli jsi nesprávně nezadala nějaké jméno. -Chvilku si s tím, ať vidíš, co se s tím dá dělat! +Hraj si s tím chvilku ať vidíš co se s tím dá dělat! ## Funkce print -Zkus toto: +Zkuste toto: -``` ->>> name = 'Maria' ->>> name -'Maria' ->>> print(name) +{% filename %}command-line{% endfilename %} + +```python +>>> 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. +Jak uvidíme později, funkce `print()` je také užitečná, když chceme vypsat věci uvnitř funkce, nebo když chceme tisknout věci 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ů :) +Vedle řetězců a celých čísel má Python další druhy různých typů objektů. Teď se podíváme na jeden co 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: -``` ->>> [] +{% filename %}command-line{% endfilename %} + +```python +>>> [] [] ``` -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é: +Ano, tento seznam je prázdný. Není velmi 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é: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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) +{% filename %}command-line{% endfilename %} + +```python +>>> 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: +Ano! Funkce `len()` ti zjistí počet objektů v seznamu. Šikovné, že? Možná by jsme je teď měli zkusit seřadit: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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) +{% filename %}command-line{% endfilename %} + +```python +>>> 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! +Jak můžeš vidět, čísla v seznamu jsou nyní seřazeny od nejnižší do nejvyšší hodnoty. Gratulujeme! -Můžeme také zkusit obrátit pořadí? Udělejme to! +Také můžeme zkusit obrátit pořadí? Udělejme to! -``` ->>> lottery.reverse() ->>> print(lottery) +{% filename %}command-line{% endfilename %} + +```python +>>> 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: +If you want to add something to your list, you can do this by typing this command: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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: +Pokud chceš zobrazit pouze první číslo, můžeš to udělat pomocí **indexů**. Index je číslo, které říká, kde v seznamu položky najde. Programátoři preferují počítání od 0, takže první objekt v seznamu je v indexu 0, další je v 1 a tak dále. Zkuste toto: -``` ->>> print(lottery[0]) -59 ->>> print(lottery[1]) +{% filename %}command-line{% endfilename %} + +```python +>>> 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. +Jak můžeš vidět, 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. +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. -``` +{% filename %}command-line{% endfilename %} + +```python >>> print(lottery) [59, 42, 30, 19, 12, 3, 199] >>> print(lottery[0]) 59 >>> lottery.pop(0) +59 >>> 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é? +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: +> 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 +>>> {} {} ``` 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): +Now, try writing the following command (try substituting your own information, too): -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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: +With this command, you just created a variable named `participant` with three key–value pairs: -* 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). +- 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']) +{% filename %}command-line{% endfilename %} + +```python +>>> print(participant['name']) Ola ``` -Je to podobné seznamu. Ale není nutné si pamatovat index - jen jméno. +See, it's similar to a list. But you don't need to remember the index – just the name. -Co se stane, když se zeptáme Pythonu na hodnotu klíče, který neexistuje? Zkus hádat! Pojďme to vyzkoušet a uvidíš! +Co se stane, když se zeptáme Pythonu na hodnotu klíče, který neexistuje? Můžeš hádat? Pojďme to vyzkoušet a uvidíš! -``` ->>> participant['age'] -Traceback (most recent call last): -File "", line 1, in +{% filename %}command-line{% endfilename %} + +```python +>>> 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. +Podívej, další chyba! Toto je **KeyError**. Python ti napomáhá a řekne ti, že klíč `"věk"` neexistuje v tomto slovníku. 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. +- Potřebuješ jen seřazenou sekvenci položek? Použij seznam. +- Pokud potřebuješ přiřadit hodnotám klíče, aby jsi 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í: +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: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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: +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) +{% filename %}command-line{% endfilename %} + +```python +>>> 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. +I hope it makes sense up to now. :) Ready for some more fun with dictionaries? Read on for some amazing things. -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: +You can use the `pop()` method to delete an item in the dictionary. Například pokud chceš odstranit záznam, kterému odpovídá klíč `"favorite_numbers"`, zadej následující příkaz: -``` +{% filename %}command-line{% endfilename %} + +```python >>> participant.pop('favorite_numbers') +[7, 42, 92] >>> participant {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} ``` -Jak vidíš, z výstupu byla odstraněna odpovídající dvojice klíč hodnota 'favorite_numbers'. +As you can see from the output, the key–value pair corresponding to the 'favorite_numbers' key has been deleted. -Kromě toho můžeš také změnit hodnotu přidruženou k již vytvořenému klíči ve slovníku. Napiš: +As well as this, you can also change a value associated with an already-created key in the dictionary. Type this: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 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. +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. ### 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 +- **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 -Jsi připravena na další část? +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: +> 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 +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 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? +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? -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. +Zajímá tě, proč jsme dali dva symboly rovná se `==` vedle sebe, pro porovnání zda-li jsou čísla stejná? Jedno rovná se `=` používáme pro přiřazení hodnoty do proměnné. You always, **always** need to put two of them – `==` – if you want to check if things are equal to each other. 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 +{% filename %}command-line{% endfilename %} + +```python +>>> 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: +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: -* 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 +- 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 +{% filename %}command-line{% endfilename %} + +```python +>>> 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ý +- **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 Už jsi někdy slyšela výraz "srovnávat jablka a hrušky"? Zkusme v Pythonu ekvivalent: -``` +{% filename %}command-line{% endfilename %} + +```python >>> 1 > 'django' Traceback (most recent call last): -File "", line 1, in -TypeError: unorderable types: int() > str() + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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. +Incidentally, you just learned about a new type of object in Python. It's called **Boolean**. + +There are only two Boolean objects: -Existují pouze dva logické objekty: - True - False +- 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.) +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well, of course.) Pravdivostní hodnoty mohou být také v proměnné! Viz zde: -``` ->>> a = True ->>> a +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a True ``` Rovněž to můžete provést takto: -``` ->>> a = 2 > 5 ->>> a +{% filename %}command-line{% endfilename %} + +```python +>>> 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` +- `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! +Gratulujeme! Logické hodnoty jsou jedny z nejbezvdnějších vlastností v programování, a právě jste se je naučili 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: +> 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. -* 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! +Zatím jsme psali 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ěli 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: -Chceš-li opustit interaktivní režim Pythonu, který jsme dosud používaly, jednoduše zadejte ~ ~ ~ exit() ~ ~ ~ funkci: +- Ukončit interaktivní režim Pythonu +- Otevřít tvůj zvolený editor kódu +- Ulož nějaký kód do nového pythnovského souboru +- Spusť ho! -``` +To exit from the Python interpreter that we've been using, simply type the `exit()` function + +{% filename %}command-line{% endfilename %} + +```python >>> 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: +Dříve jsi si vybrala editor kódu v části [editor kódu](../code_editor/README.md). Nyní potřebujeme otevřít editor a napsat vlastní kód do nového souboru: - [2]: ../code_editor/README.md +{% filename %}editor{% endfilename %} ```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ý jsi se dnes naučila. -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žte jej na plochu. Soubor můžeš pojmenovat jakkoliv chceš, ale důležitá věc je, aby jsi se ujistila, že soubor končí na **.py**. The **.py** extension tells our operating system that this is a **Python executable file** and Python can run it. -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. +> **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. To se nazývá "zvýrazňování syntaxe" a je to opravdu užitečná funkce při kódování. 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). To je jeden z důvodů, proč používáme editory kódu. :) -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. +Pokud máš soubor uložen je čas jej spustit! Pomocí dovedností, které jsi se naučila v sekci příkazová řádka, pomocí terminálu **změň adresář** na plochu. + + Na Macu bude příkaz vypadat přibližně takto: -``` -$ cd ~/Desktop -``` +{% filename %}command-line{% endfilename %} -Na Linuxu to bude vypadat takto (slovo "Desktop" (Plocha) může být přeloženo do tvého jazyka): + $ cd ~/Desktop + -``` -$ cd ~/Desktop -``` + -A na Windows to bude vypadat takto: + -``` -> cd %HomePath%\Desktop -``` +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\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! +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +> python python_intro.py ``` 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 +## 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**. +Lots of things in code should be executed only when given conditions are met. That's why Python has something called **if statements**. Nahraďte kód v souboru **python_intro.py** tímto: +{% filename %}python_intro.py{% endfilename %} + ```python if 3 > 2: ``` -Pokud jsi soubor uložila a spustila, pravděpodobně uvidíš následující chybu: +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 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 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: + +{% filename %}python_intro.py{% endfilename %} ```python if 3 > 2: - print('It works!') + 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. +Všimla sis, jak jsme odsadili 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 true. 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 +{% 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. + ### 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`: +{% filename %}python_intro.py{% endfilename %} + ```python if 5 > 2: - print('5 is indeed greater than 2') + print('5 is indeed greater than 2') else: - print('5 is not greater than 2') + print('5 is not greater than 2') ``` -Pokud je výraz pravdivý, po spuštění se vytiskne: +Pokud je výraz pravdivý po spuštění se vytiskne: -``` -$ python3 python_intro.py -5 is not greater than 2 -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + 5 is indeed greater than 2 + -Kdyby 2 bylo větší než 5, spustil by se první příkaz. Jak snadné! Podívejme se, jak funguje `elif`: +If 2 were a greater number than 5, then the second command would be executed. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} ```python name = 'Sonja' if name == 'Ola': - print('Hey Ola!') + print('Hey Ola!') elif name == 'Sonja': - print('Hey Sonja!') + print('Hey Sonja!') else: - print('Hey anonymous!') + print('Hey anonymous!') ``` a spusť: -``` -$ python3 python_intro.py -Hey Sonja! -``` +{% filename %}command-line{% endfilename %} + + $ 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ří. +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: +Můžeš přidat tolik `elif` příkazů, kolik se ti zlíbí po počátečním `if`. Například: + +{% filename %}python_intro.py{% endfilename %} ```python volume = 57 if volume < 20: - print("Je to dost potichu.") + print("It's kinda quiet.") elif 20 <= volume < 40: - print("Jako hudba v pozadí dobré.") + print("It's nice for background music") elif 40 <= volume < 60: - print("Skvělé, slyším všechny detaily.") + print("Perfect, I can hear all the details") elif 60 <= volume < 80: - print("Dobré na party.") + print("Nice for parties") elif 80 <= volume < 100: - print("Trochu moc nahlas!") + print("A bit loud!") else: - print("Krvácí mi uši!") + print("My ears are hurting! :(") ``` Python prochází a testuje každou položku v posloupnosti a vypíše: +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + dokonalé, můžete slyšet všechny detaily + + +## 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!") ``` -$ python3 python_intro.py - Skvělé, slyším všechny detaily. -``` + +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. ### Shrnutí -V posledních třech cvičeních ses dozvěděla o: +In the last few exercises you learned about: -* **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. +- **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 Č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! +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +Remember functions like `len()` that you can execute in Python? Well, good news – you will learn how to write your own functions now! + +Funkce je sled instrukcí, které by měl Python provést. Každá funkce v Pythonu začíná s klíčovým slovem `def`, dále je uveden název a funkce může mít také nějaké parametry. Let's give it a go. Nahraď kód v **python_intro.py** následujícím: -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: +{% filename %}python_intro.py{% endfilename %} ```python def hi(): - print('Hi there!') - print('How are you?') + 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íš). +Asi se divíš, proč jsme napsali 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 jí zavoláš/spustíš). -Tak to teď zkus a uvidíš, co se stane: +Tak to teď zkus a uvidíš co se stane: -``` -$ python3 python_intro.py -Hi there! -How are you? -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: -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í: +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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): ``` -Jak vidíš, nyní jsme přidaly naší funkci parametr, `name`: +Jak vidíš, nyní jsme přidali naší funkci parametr, `name`: + +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): - if name == 'Ola': - print('Hi Ola!') - elif name == 'Sonja': - print('Hi Sonja!') - else: - print('Hi anonymous!') + 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' -``` +{% 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' + -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: +Jejda chyba. Naštěstí Python nám vypsal docela užitečné chybovou zprávu. Jak můžeš vidět nyní funkce `hi()` (kterou jsme definovali) má jeden povinný parametr `(s názvem name)` a zapomněli jsme ho předat při volání funkce. Pojďme to opravit v následující části: + +{% filename %}python_intro.py{% endfilename %} ```python hi("Ola") ``` -A znovu jej spusť: +A znovu jej spusťte: -``` -$ python3 python_intro.py -Hi Ola! -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Ola! + -A co když změníme jméno? +Pokud změníme jméno? + +{% filename %}python_intro.py{% endfilename %} ```python hi("Sonja") ``` -Spustíme: +S SpuStíme: -``` -$ python3 python_intro.py -Hi Sonja! -``` +{% filename %}command-line{% endfilename %} -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: + $ python3 python_intro.py + Hi Sonja! + -``` -Hi anonymous! -``` +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: + +{% filename %}command-line{% endfilename %} + + Hi anonymous! + + +To je paráda, co? Nemusíš se opakovat a měnit touto cestou jméno pokaždé, když chceš aby funkce pozdravila jinou osobu. And that's exactly why we need functions – you never want to repeat your code! -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! +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? -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? +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): - print('Hi ' + name + '!') + print('Hi ' + name + '!') hi("Rachel") ``` Pojďme zavolat náš nový kód: -``` -$ python3 python_intro.py -Hi Rachel! -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + -Blahopřejeme! Právě ses naučila, jak psát funkce :) +Blahopřejeme! Právě jste se naučili, jak psát funkce! :) ## Smyčky/Loops +> For readers at home: this part is covered in the [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) video. + 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. +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: +{% filename %}python_intro.py{% endfilename %} + ```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: +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: + +{% filename %}python_intro.py{% endfilename %} ```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. +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. Zde je celý kód, který umístíme do souboru: +{% filename %}python_intro.py{% endfilename %} + ```python def hi(name): - print('Hi ' + name + '!') + print('Hi ' + name + '!') girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] for name in girls: - hi(name) - print('Next girl') + 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 -``` +{% filename %}command-line{% endfilename %} -Jak vidíš, vše, co jsi vložila dovnitř příkazu `for` s odsazením, se zopakuje pro každý prvek seznamu `girls`. + $ 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 můžeš vidět, vše co jsi vložila dovnitř příkazu `for` s odsazením, se zopakuje pro každý element seznamu `girls`. Ve funkci `for` můžeš také použít čísla pomocí funkce `range`: +{% filename %}python_intro.py{% endfilename %} + ```python for i in range(1, 6): print(i) @@ -824,24 +1039,23 @@ for i in range(1, 6): Což ti vypíše: -``` -1 -2 -3 -4 -5 -``` +{% filename %}command-line{% endfilename %} -`range` je funkce, která vytvoří seznam s posloupností čísel (tato čísla zadáváš jako parametry funkce). + 1 + 2 + 3 + 4 + 5 + -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í. +`range` je funkce, která vytvoří seznam s posloupností čísel (tyto čísla zadáváš jako parametry funkce). -## Shrnutí +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). That is because "range" is half-open, and by that we mean it includes the first value, but not the last. -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! +## Shrnutí -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. :) +A je to. **Jsi naprosto skvělá!** To byla složitá kapitola, takže měla bys být na sebe hrdá. My jsme na tebe velmi hrdí za to, že jsi se dostala tak daleko! -![Hrnek][3] +You might want to briefly do something else – stretch, walk around for a bit, rest your eyes – before going on to the next chapter. :) - [3]: images/cupcake.png +![Hrnek](images/cupcake.png) \ No newline at end of file diff --git a/cs/signup_pythonanywhere.md b/cs/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/cs/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/cs/template_extending/README.md b/cs/template_extending/README.md index 184c85aa05b..2228fed2070 100755 --- a/cs/template_extending/README.md +++ b/cs/template_extending/README.md @@ -1,106 +1,130 @@ # 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. +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é! +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! -## Vytvoření základní šablony +## Create a base template -Základní šablona je šablona, kterou použijeme na každé stránce našich webových stránek. +Základní šablona je šablona, kterou rozšíříme 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 -``` + blog + └───templates + └───blog + base.html + post_list.html + + +Pak jej otevři a zkopírujte vše z `post_list.html` do `base.html` souboru, jako je to níže: -Pak jej otevři a zkopíruj vše z `post_list.html` do `base.html` souboru, jako je to níže: +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% load staticfiles %} - - Django Girls blog - - - - - - - -
-
-
- {% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
- {% endfor %} -
-
-
- + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ -``` +``` + +Pak v `base.html`, nahraď celé `< body >` (vše mezi `< body >` a `< / body >`) tímto: -Pak v `base.html` nahraď celé `` (vše mezi `` a ``) tímto: +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html - -
-
-
- {% block content %} - {% endblock %} -
-
-
+ +
+
+
+ {% block content %} + {% endblock %} +
+
+
``` -Nahradili jsme v podstatě všechno, co bylo mezi `{% for post in posts %}{% endfor %}`, za: +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```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. +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`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: +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
+
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
{% endfor %} -``` +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! -A teď přidej na začátek souboru tento řádek: +{% 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 %}`. Takto:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html -{% extends 'blog/base.html' %} -``` +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` -{% 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 %}`. Takto: {% endraw %} +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' %} @@ -116,8 +140,8 @@ A teď přidej na začátek souboru tento řádek: {% endfor %} {% endblock %} -``` +``` -To je ono! Zkontroluj, zda tvoje stránky stále správně fungují :) +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`. +> 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. \ No newline at end of file diff --git a/cs/whats_next/README.md b/cs/whats_next/README.md index 5c52f3bfb88..061da70e702 100755 --- a/cs/whats_next/README.md +++ b/cs/whats_next/README.md @@ -1,40 +1,25 @@ # Co dál? -Můžeš si pogratulovat! **Jsi naprosto úžasná**. Jsme na tebe hrdí! < 3 +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ň: +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. -* Sleduj Django Girls na [Facebooku][1] nebo [Twitteru][2] a zůstaň v obraze +### Můžete mi doporučit nějaké další zdroje? - [1]: http://facebook.com/djangogirls - [2]: https://twitter.com/djangogirls +Yes! First, go ahead and try our other book, called [Django Girls Tutorial: Extensions](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). -### Můžete mi doporučit nějaké další zdroje? +Later on, you can try the resources listed below. They're all very recommended! -Ano! Zaprvé, jdi a zkus naši další knihu, jmenuje se [Django Girls Tutorial: Extensions][3]. - - [3]: https://tutorial-extensions.djangogirls.org - -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://www.gettingstartedwithdjango.com/ - [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/de-DE/GLOSSARY.md b/de-DE/GLOSSARY.md new file mode 100644 index 00000000000..26a8c07100e --- /dev/null +++ b/de-DE/GLOSSARY.md @@ -0,0 +1,3 @@ +# Code-Editor + +Ein Code-Editor ist eine Anwendung, die es dir erlaubt, deinen Code zu speichern, um später daran weiterzuarbeiten. Du kannst in dem [Code-Editor Kapitel](./code_editor/README.md) erfahren, woher du einen bekommst. \ No newline at end of file diff --git a/de-DE/README.md b/de-DE/README.md new file mode 100644 index 00000000000..517f362d1bb --- /dev/null +++ b/de-DE/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> Dieses Werk ist unter der Creative Commons Attribution-ShareAlike 4.0 International License lizensiert. Eine Kopie dieser Lizenz finden Sie auf http://creativecommons.org/licenses/by-sa/4.0/ + +## Willkommen + +Willkommen beim Django Girls Tutorial! Wir freuen uns, dass du hier bist. :) In diesem Tutorial schauen wir gemeinsam unter die Haube der Technologien im Internet, geben dir einen Einblick in die Bits und Bytes, die zusammen das Internet bilden, wie wir es heute kennen. + +Wie alles Unbekannte wird das ein Abenteuer sein – aber keine Sorge: Da du bereits den Mut aufgebracht hast, hier zu sein, wirst du das schon meistern. :) + +## Einleitung + +Hattest du auch schon einmal das Gefühl, dass Technik in der Welt immer wichtiger wird und du da nicht ganz mithalten kannst? Wolltest du schon immer einmal eine Website bauen, aber hattest dann nicht genug Motivation, damit anzufangen? Hast du dir irgendwann schon einmal gedacht, dass die Computerwelt zu kompliziert für dich ist, so dass du noch nicht einmal den Versuch unternommen hast, dort selbst etwas zu tun? + +Dann haben wir hier gute Neuigkeiten für dich! Programmieren ist nicht so schwer, wie du denkst, und wir zeigen dir hier, wie viel Spaß es machen kann. + +Dieses Tutorial wird dich nicht auf zauberhafte Weise in eine Programmiererin verwandeln. Wenn du gut darin sein willst, brauchst du Monate oder sogar Jahre des Lernens und Übens. Aber wir wollen dir zeigen, dass Programmieren oder Webseitenerstellen nicht so kompliziert ist, wie es scheint. Wir versuchen, dir auf einfache Art verschiedene, kleine Teile zu zeigen, so dass du davon nicht eingeschüchtert wirst. + +Wir hoffen, dass du danach diese Technik und Technologien so sehr mögen wirst wie wir! + +## Was lernst du in diesem Tutorial? + +Wenn du mit dem Tutorial fertig bist, hast du eine einfache, aber funktionierende Webanwendung: deinen eigenen Blog. Wir zeigen dir, wie man ihn online stellt, andere können dein Werk also sehen! + +Es wird (in etwa) so aussehen: + +![Abbildung 0.1](images/application.png) + +> Wenn du allein mit diesem Tutorial arbeitest und keinen Coach in der Nähe hast, kannst du in diesem Chat nachfragen, wenn du ein Problem hast: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). Wir haben unsere Coaches und frühere Teilnehmer unserer Workshops gebeten, hin und wieder dort vorbei zu schauen und anderen mit dem Tutorial zu helfen! Hab keine Angst, dort deine Fragen zu stellen! + +Okay, [lass uns ganz am Anfang starten...](./how_the_internet_works/README.md) + +## Das Tutorial daheim durcharbeiten + +An einem Django-Girls-Workshop teilzunehmen ist toll, aber uns ist klar, dass das nicht immer allen möglich ist. Darum wollen wir dich ermutigen, das Tutorial auch zu Hause zu erarbeiten. Für Leser zu Hause erstellen wir gerade Video-Tutorials, die es erleichtern sollen, diesem Tutorial zu folgen. Diese Arbeit ist noch nicht abgeschlossen, aber mehr und mehr Themen werden als Video erfasst und können im [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed)-YouTube-Kanal angesehen werden. + +In jedem Kapitel, das bereits mit Video unterstützt wird, gibt es einen Link auf das jeweilige Video dazu. + +## Über uns und wie du mithelfen kannst + +Dieses Tutorial wird von [DjangoGirls](https://djangogirls.org/) betreut. Solltest du Fehler finden oder das Tutorial aktualisieren wollen, dann folge den [Richtlinien zum Mitarbeiten](https://github.com/DjangoGirls/tutorial/blob/master/CONTRIBUTING.md). + +## Möchtest du uns helfen, das Tutorial in andere Sprachen zu übersetzen? + +Zur Zeit haben wir die Übersetzungen auf der crowdin.com Plattform: + +https://crowdin.com/project/django-girls-tutorial + +Sollte deine Sprache nicht aufgeführt sein, dann öffne ein neues [Issue](https://github.com/DjangoGirls/tutorial/issues/new), mit der betreffenden Sprache, dann können wir sie hinzufügen. \ No newline at end of file diff --git a/de-DE/SUMMARY.md b/de-DE/SUMMARY.md new file mode 100644 index 00000000000..28b069b3a29 --- /dev/null +++ b/de-DE/SUMMARY.md @@ -0,0 +1,35 @@ +# Zusammenfassung + +* [Einleitung](README.md) +* [Installation](installation/README.md) + * [Kommandozeile](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Code-Editor](installation/README.md#code-editor) + * [Virtuelle Umgebung](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Installation (Chromebook)](chromebook_setup/README.md) +* [Wie das Internet funktioniert](how_the_internet_works/README.md) +* [Einführung in die Kommandozeile](intro_to_command_line/README.md) +* [Python-Installation](python_installation/README.md) +* [Der Code-Editor](code_editor/README.md) +* [Einführung in Python](python_introduction/README.md) +* [Django - Was ist das?](django/README.md) +* [Django-Installation](django_installation/README.md) +* [Dein erstes Django-Projekt!](django_start_project/README.md) +* [Django-Models](django_models/README.md) +* [Django-Administration](django_admin/README.md) +* [Veröffentlichen!](deploy/README.md) +* [Django-URLs](django_urls/README.md) +* [Django-Views - leg los!](django_views/README.md) +* [Einführung in HTML](html/README.md) +* [Django-ORM und QuerySets](django_orm/README.md) +* [Dynamische Daten in Templates](dynamic_data_in_templates/README.md) +* [Django-Templates](django_templates/README.md) +* [CSS - mach es hübsch!](css/README.md) +* [Erweiterung der Templates](template_extending/README.md) +* [Erweitere deine Anwendung](extend_your_application/README.md) +* [Django-Formulare](django_forms/README.md) +* [Wie geht es weiter?](whats_next/README.md) \ No newline at end of file diff --git a/de-DE/chromebook_setup/README.md b/de-DE/chromebook_setup/README.md new file mode 100644 index 00000000000..4e1c50d4085 --- /dev/null +++ b/de-DE/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook-Installation + +> **Hinweis** Wenn du die [Installation bereits gemacht](../installation/README.md) hast, kannst du direkt zur [Einführung in Python](../python_introduction/README.md) gehen. + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/de-DE/chromebook_setup/instructions.md b/de-DE/chromebook_setup/instructions.md new file mode 100644 index 00000000000..8503cc13236 --- /dev/null +++ b/de-DE/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Du kannst [diesen Abschnitt einfach](http://tutorial.djangogirls.org/en/installation/#install-python) überspringen, falls du kein Chromebook benutzt. Wenn du eins benutzt, wird deine Installation ein wenig anders sein. Du kannst den Rest der Installationsanweisungen ignorieren. + +### Cloud-IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Eine Cloud-IDE ist ein Werkzeug, dass dir einen Code-Editor und Zugang zu einem Rechner im Internet bereitstellt, auf dem du die Software installieren, anpassen und ausführen kannst. Für die Dauer des Tutorials wird Cloud IDE zu deinem *lokalen Rechner*. Auch du wirst Befehle in einer Kommandozeilen-Oberfläche ausführen können, genau wie die anderen Teilnehmerinnen, die mit OS X, Ubuntu oder Windows arbeiten. Dein Terminal wird jedoch mit einem Rechner verbunden sein, den Cloud IDE dir bereitstellt. Hier sind die Anleitungen für die Cloud-IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). Wähle eine der Cloud-IDEs aus und folge den Anweisungen der gewählten Cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Gehe zu [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Lege dir dort ein Benutzerkonto an +3. Klicke auf *New Server* und wähle die Django-App +4. Klicke auf die Schaltfläche "Terminal" (links im Browserfenster) + +Jetzt solltest du links eine Schnittstelle mit einer Seitenleiste und Schaltflächen sehen. Klicke auf den "Terminal"-Button und öffne das Terminal-Fenster mit einer Eingabeaufforderung wie folgt: + +{% filename %}browser{% endfilename %} + + $ + + +Das Terminal auf der PaizaCloud Cloud IDE steht für deine Anweisungen bereit. Du kannst die Größe des Fensters frei einstellen. + +#### AWS Cloud9 + +Zur Zeit verlangt Cloud 9, dass du dich mit AWS anmeldest und Kreditkarten-Informationen angibst. + +1. Installiere Cloud 9 aus dem [Chrome web store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Gehe zu [c9.io](https://c9.io) und klicke auf *Get started with AWS Cloud9* +3. Erstelle ein AWS-Benutzerkonto (benötigt Angabe der Kreditkarte, kann aber kostenlos verwendet werden) +4. Gib im AWS-Dashboard *Cloud9* in die Suchzeile ein und klicke es an +5. Klicke im Cloud-9-Dashboard *Create environment* an +6. Gib ihm den Namen *django-girls* +7. Wähle beim Konfigurieren der Einstellungen *Create a new instance for environment (EC2)* als "Environment Type" und den "Instance type" *t2.micro* ("Free-tier eligible." sollte angezeigt werden). Die Voreinstellung bzgl. "cost-saving" ist in Ordnung und auch die anderen Voreinstellungen kannst du belassen. +8. Klicke auf *Next step* +9. Klicke auf *Create environment* + +Jetzt solltest du eine Benutzeroberfläche mit Seitenleiste, ein grosses Fenster mit Text und am unteren Rand ein Feld sehen, das wie folgt aussieht: + +{% filename %}bash{% endfilename %} + + deinbenutzername:~/workspace $ + + +Dieser untere Bereich ist dein Terminal. Dort kannst du Kommandos für den Computer eingeben, den dir Cloud 9 zur Verfügung stellt. Du kannst dieses Fenster vergrößern oder verkleinern. + +#### Glitch.com Cloud-IDE + +1. Gehe auf [Glitch.com](https://glitch.com/) +2. Melde dich für einen Account an (https://glitch.com/signup) oder nutze deinen GitHub-Account, falls du einen hast. (Siehe GitHub-Anweisungen unten.) +3. Klicke auf *Neues Projekt* und wähle *hello-webpage* +4. Klicke auf die Dropdown-Liste Tools (unten links im Fenster) und dann auf den Knopf Terminal, um einen Kommandozeilen-Tab mit einem Prompt wie dem folgenden zu öffnen: + +{% filename %}Terminal{% endfilename %} + + app@name-deines-glitch-projects:~ + + +Wenn du Glitch.com als Cloud-IDE verwendest, musst du keine virtuelle Umgebung erstellen. Erstelle stattdessen die folgenden Dateien manuell: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Gehe nach dem Erstellen der Dateien zum Terminal und führe die folgenden Befehle aus, um dein erstes Django-Projekt zu erstellen: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +Um detaillierte Fehlermeldungen zu sehen, kannst du Django Debug-Logs für deine Glitch-Anwendung aktivieren. Füge einfach folgendes am Ende der Datei `mysite/settings.py` hinzu. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +Dadurch wird eine Datei namens `debug.log` erzeugt, die aufgetretene Django-Operationen und Fehlermeldungen detailliert aufgeführen wird, was die Fehlersuche und -behebung sehr erleichtern kann, wenn deine Website nicht funktioniert. + +Der erste Neustart des Glitch-Projekts sollte fehlschlagen. (Wenn du auf die oberste Dropdown-Schaltfläche `Show` klickst und dann auf `In a New Window`, erhältst du die Fehlermeldung `DisallowedHost`.) Mach dir jetzt keine Sorgen darüber. Das Tutorial wird dies beheben, sobald du die Django-Einstellungen deines Projekts in der Datei `mysite/settings.py` aktualisierst + +### Virtuelle Umgebung + +Eine virtuelle Umgebung (auch virtualenv genannt) ist wie ein privater Behälter, in den wir nützlichen Code für ein Projekt packen können, an dem wir arbeiten. Wir benutzen sie, um Code für verschiedene Projekte getrennt aufzubewahren, damit dieser nicht vermischt wird. + +Führe Folgendes aus: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(Beachte, dass wir im letzten Befehl eine Tilde gefolgt von einem Gleichheitssymbol benutzen: `~=`). + +### GitHub + +Erstelle einen [GitHub](https://github.com)-Account. + +### PythonAnywhere + +Das Django Girls-Tutorial enthält ein Kapitel zum Thema Deployment. Beim Deployment nimmst du den Code, der deiner Web-Anwendung zu Grunde liegt, und packst ihn auf einen öffentlich zugänglichen Computer (Server), damit auch andere Leute deine Arbeit sehen können. + +Es mag seltsam scheinen, das auf einem Chromebook zu tun. Denn wir sind mit Cloud 9 ja bereits auf einem anderen Computer im Internet (anstatt z.B. auf einem lokalen Laptop). Es ist aber trotzdem sinnvoll, denn wir können uns unseren Cloud-9-Arbeitsplatz als Ort für "Dinge in Arbeit" vorstellen und PythonAnywhere als Ort, wo wir unser "fertiges" Projekt der Öffentlichkeit zeigen. + +Melde dich deshalb auf [www.pythonanywhere.com](https://www.pythonanywhere.com) für ein PythonAnywhere-Benutzerkonto an. \ No newline at end of file diff --git a/de-DE/code_editor/README.md b/de-DE/code_editor/README.md new file mode 100644 index 00000000000..9ff0e2c9c79 --- /dev/null +++ b/de-DE/code_editor/README.md @@ -0,0 +1,11 @@ +# Der Code-Editor + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) behandelt. + +Gleich geht's los! Du wirst deine erste Zeile Programmcode schreiben! Daher ist es jetzt an der Zeit, einen entsprechenden Editor herunterzuladen! + +> **Hinweis** Wenn du ein Chromebook benutzt, dann überspringe dieses Kapitel und folge den [Chromebook Installations](../chromebook_setup/README.md)-Anweisungen. Deine Cloud-IDE (PaizaCloud Cloud IDE oder AWS Cloud9) enthält einen Code-Editor und wenn du eine Datei in deiner Entwicklungsumgebung öffnest, wirst du automatisch den Editor benutzen. +> +> **Hinweis:** Es kann sein, dass du diesen Schritt bereits im [Kapitel "Installation"](../installation/README.md) erledigt hast. In diesem Fall kannst du direkt zum nächsten Kapitel übergehen! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/de-DE/code_editor/instructions.md b/de-DE/code_editor/instructions.md new file mode 100644 index 00000000000..4583934fabf --- /dev/null +++ b/de-DE/code_editor/instructions.md @@ -0,0 +1,37 @@ +Es gibt viele verschiedene Editoren. Welcher für dich am besten ist, ist weitestgehend Geschmackssache. Die meisten Python-Programmiererinnen verwenden komplexe, aber extrem leistungsfähige IDEs (Integrated Development Environments), z. B. PyCharm. Für Anfängerinnen sind diese jedoch weniger gut geeignet. Unsere Empfehlungen sind ebenso leistungsfähig, aber viel einfacher zu bedienen. + +Unsere Vorschläge siehst du unten. Aber fühl dich ganz frei, deine Trainerin zu fragen, was ihre Vorlieben sind - wenn sie sich mit dem Editor auskennt, wird es leichter sein, Hilfe zu erhalten. + +## Visual Studio Code + +Visual Studio Code ist ein von Microsoft entwickelter Quellcode-Editor für Windows, Linux und Mac. Es enthält Unterstützung für Debugging, eingebaute Git-Steuerung, Syntax-Highlighting, intelligente Code-Vervollständigung, Snippets und Code-Refactoring. + +[Du kannst ihn hier herunterladen](https://code.visualstudio.com/) + +## Gedit + +Gedit ist ein kostenloser Open-Source-Editor. Es gibt ihn für alle Betriebssysteme. + +[Du kannst ihn hier herunterladen](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text ist ein sehr beliebter Editor, nutzbar für einen kostenlosen Testzeitraum. Er ist einfach zu installieren und zu verwenden, und er ist für alle Betriebssysteme verfügbar. + +[Du kannst ihn hier herunterladen](https://www.sublimetext.com/3) + +## Atom + +Atom ist ein weiterer beliebter Editor. Er ist gratis, Open-Source und für Windows, OS X und Linux verfügbar. Atom wird von [GitHub](https://github.com/) entwickelt. + +[Du kannst ihn hier herunterladen](https://atom.io/) + +## Warum installieren wir einen Code-Editor? + +Vielleicht wunderst du dich, warum wir so spezielle Code-Editor-Software installieren, statt einfach etwas wie Word oder Notepad zu benutzen. + +Erstens muss Code "plain text" (unformatierter Text) sein. Das Problem mit Programmen wie Word und Textedit ist, dass sie nicht "plain text" sondern "rich text" (mit Schriftarten und Formatierungen) produzieren und besondere Formate wie RTF (Rich Text Format) verwenden. + +Ein weiterer Grund ist, dass Code-Editoren (bisweilen auch Programmier- oder Text-Editoren genannt) auf das Bearbeiten von Programm-Code spezialisiert sind und Funktionen aufweisen, die normale Textverarbeitungen nicht haben. Beispielsweise sogenanntes "Syntax-Highlighting", also farbliches Hervorheben bestimmter Code-Stellen, oder auch das automatische Schließen von Klammern und vieles mehr. + +Einiges davon werden wir später in Aktion sehen. Glaub uns: es wird nicht lange dauern, bis du deinen Code-Editor nicht mehr missen möchtest. :) \ No newline at end of file diff --git a/de-DE/css/README.md b/de-DE/css/README.md new file mode 100644 index 00000000000..f439d56e9e9 --- /dev/null +++ b/de-DE/css/README.md @@ -0,0 +1,330 @@ +# CSS - mach es hübsch! + +Unser Blog sieht immer noch ziemlich unfertig aus, oder? Zeit, das zu ändern! Dafür nutzen wir CSS. + +## Was ist CSS? + +Cascading Style Sheets (CSS) ist eine Sprache, die das Aussehen und die Formatierung einer Website beschreibt. Es handelt sich wie bei HTML um eine Auszeichnungssprache (Markup Language). Sie ist sowas wie das "Make-up" unserer Website. ;) + +Aber wir wollen nicht nochmal bei Null anfangen, oder? Einmal mehr werden wir etwas verwenden, dass ProgrammiererInnen entwickelt haben und gratis im Internet zur Verfügung stellen. Wir wollen ja nicht das Rad neu erfinden. + +## Lass uns Bootstrap verwenden! + +Bootstrap ist eines der bekanntesten HTML- und CSS-Frameworks für die Entwicklung von schönen Webseiten: https://getbootstrap.com/ + +Es wurde ursprünglich von ProgrammiererInnen bei Twitter geschrieben. Heute wird es von Freiwilligen aus der ganzen Welt weiterentwickelt! + +## Bootstrap installieren + +Öffne deine `.html`-Datei in deinem Code-Editor und füge Folgendes zum ``-Abschnitt hinzu, um Bootstrap zu installieren: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Dadurch werden deinem Projekt keine Dateien hinzugefügt. Der Code verweist nur auf Dateien, die im Internet vorhanden sind. Öffne und aktualisiere also deine Webseite. Da ist sie! + +![Abbildung 14.1](images/bootstrap1.png) + +Sie sieht jetzt schon viel schöner aus! + +## Statische Dateien in Django + +Endlich werden wir einen genaueren Blick auf die Dinge werfen, die wir bisher **statische Dateien** genannt haben. Statische Dateien sind alle deine CSS- und Bilddateien. Ihr Inhalt hängt nicht vom Requestkontext ab, sondern gilt für alle Benutzer gleichermaßen. + +### Wohin kommen die statischen Dateien für Django + +Django weiss schon, wo die statischen Dateien für die integrierte "admin"-App zu finden sind. Wir müssen noch die statischen Dateien für unsere `blog`-App hinzufügen. + +Dies tun wir, indem wir einen Ordner namens `static` in der Blog-App erstellen: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │ └── templates + └── mysite + + +Django findet automatisch alle Ordner mit dem Namen "static" in all unseren App-Ordnern. So ist es in der Lage, ihre Inhalte als statische Dateien zu nutzen. + +## Deine erste CSS-Datei! + +Erstellen wir nun eine CSS-Datei, um deiner Website deinen eigenen Stil zu verleihen. Erstelle ein neues Verzeichnis namens `css` in deinem `static`-Verzeichnis. Dann erstelle eine neue Datei namens `blog.css` in diesem `css`-Verzeichnis. Fertig? + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +Zeit, ein wenig CSS zu schreiben! Öffne die `blog/static/css/blog.css` Datei in Deinem Code-Editor. + +Wir gehen nicht zu sehr auf die Details von CSS ein. Für diejenigen, die mehr über CSS lernen möchten, haben wir am Ende des Kapitels einen Link auf eine Empfehlung für einen kostenlosen CSS-Kurs angefügt. + +Aber lass uns wenigstens etwas Kleines probieren. Beispielsweise könnten wir die Farbe unserer Kopfzeile ändern. Computer benutzen spezielle Codes, um Farben zu verstehen. Diese Codes starten immer mit `#`, danach folgen sechs Buchstaben (A-F) und Zahlen (0-9). Blau zum Beispiel ist `#0000FF`. Beispiele für solche Farbcodes findest du hier: http://www.colorpicker.com/. Du kannst auch [vordefinierte Farben](http://www.w3schools.com/colors/colors_names.asp) wie `red` und `green` benutzen. + +In deiner `blog/static/css/blog.css` Datei änderst du den folgenden Code: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1 a` ist ein CSS-Selektor. Das bedeutet, dass wir für ein `a`-Element innerhalb eines `h1`-Elements einen Style hinzufügen; der `h2 a`-Selektor macht das selbe für `h2`-Elemente. Wenn wir also etwas haben wie: `

link

` wird der `h1 a` Style angewandt. In diesem Fall sagen wir, dass die Farbe in `#C25100` geändert werden soll. Das ist ein dunkles Orange. Du kannst hier auch deine eigene Farbe verwenden, aber stelle sicher, dass sie einen guten Kontrast zum weißen Hintergrund hat! + +In einer CSS-Datei werden Stile für Elemente der HTML-Datei festgelegt. Ein Weg, HTML-Elemente zu identifizieren, ist der Name des Elements. Du erinnerst dich vielleicht an diese Namen, die wir als 'Tags' im HTML Kapitel bezeichnet haben. Zum Beispiel sind `a`, `h1` und `body` solche Elementnamen. Wir identifizieren Elemente auch über die Attribute `class` oder `id`. Klassen (`class`) und IDs (`id`) sind Namen, die du den Elementen selbst gibst. Klassen definieren dabei Gruppen von Elementen und IDs verweisen auf bestimmte Elemente. Du könntest zum Beispiel das folgende Element anhand des Elementnamens `a`, anhand der Klasse `external_link` oder anhand der ID `link_to_wiki_page` identifizieren: + +```html + +``` + +[Auf w3schools](http://www.w3schools.com/cssref/css_selectors.asp) erfährst du mehr über CSS-Selektoren. + +Wir müssen der HTML-Vorlage noch sagen, dass wir CSS eingefügt haben. Öffne die Datei `blog/templates/blog/post_list.html` im Code-Editor und füge diese Zeile ganz oben ein: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +Wir laden hier die statischen Dateien. :) Füge zwischen den Tags `` und ``, direkt nach den Links zu den Bootstrap-Dateien, noch diese Zeile ein: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Der Browser liest die Dateien in der Reihenfolge, in der sie aufgeschrieben wurden. Darum müssen wir sicherstellen, dass die Zeile am richtigen Ort steht. Sonst könnte der Code der Bootstrap-Dateien den Code aus unserer Datei überschreiben. Wir haben also unserem Template gerade gesagt, wo sich die CSS-Datei befindet. + +Deine Datei sollte jetzt so aussehen: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, speichere die Datei und lade die Seite neu! + +![Abbildung 14.2](images/color2.png) + +Gut gemacht! Vielleicht wollen wir unserer Webseite etwas mehr Luft geben, indem wir den Abstand auf der linken Seite vergrößern? Probieren wir es aus! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +Füge dies zu deinem CSS hinzu, speichere die Datei und schau dir an, was passiert. + +![Abbildung 14.3](images/margin2.png) + +Vielleicht können wir auch die Schrift in unserem HTML-Kopf anpassen? Füge dies zu `` in `blog/templates/blog/post_list.html` hinzu: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Wie eben bereits gemacht, prüfe die Reihenfolge und platziere die Anweisung vor dem Link `blog/static/css/blog.css`. Sie importiert eine Schriftart (engl. "Font") namens *Lobster* von Google Fonts (https://www.google.com/fonts). + +Suche den Anweisungsblock: `h1 a` (der Code zwischen den geschweiften Klammern `{` und `}`) in der CSS Datei `blog/static/css/blog.css`. Nun füge die Zeile `font-family: 'Lobster';` zwischen den geschweiften Klammern hinzu und aktualisiere die Seite: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Abbildung 14.3](images/font.png) + +Super! + +Wie oben erwähnt, basiert CSS auf dem Konzept von Klassen. Diese erlauben dir, einen Teil des HTML-Codes mit einem Namen zu versehen und die Darstellung dieses Teils separat von anderen Teilen mit einem Stil zu steuern. Das kann sehr hilfreich sein! Eventuell hast Du zwei 'div's die etwas vollkommen Verschiedenes auszeichnen (wie einen Seitentitel oder Post Beitrag). Die Klasse hilft dir, sie unterschiedlich aussehen zu lassen. + +Geben wir also einigen Teilen deines HTML-Codes solche Namen. Ersetze den `header`, der deine Kopfzeile enthält, mit folgendem: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Jetzt fügen wir dem `article` für den Blog-Inhalt (Post) noch eine Klasse `post` hinzu. + +{% filename %}blog/templates/blog/post_list{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Wir erweitern jetzt unser CSS mit entsprechenden Selektoren. Selektoren, die mit `.` anfangen, beziehen sich auf Klassen im HTML. Es gibt im Internet viele gute Tutorials und Informationen über CSS, die dir helfen können, den folgenden Code besser zu verstehen. Kopiere zunächst folgenden Text in deine `blog/static/css/blog.css`-Datei: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Der HTML-Code, der für die Anzeige der Blogposts verantwortlich ist, soll durch Klassen erweitert werden. Ersetze den folgenden Code: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in `blog/templates/blog/post_list.html` durch diesen: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Speichere die geänderten Dateien und aktualisiere die Webseite. + +![Abbildung 14.4](images/final.png) + +Juhuu! Sieht super aus, oder? Schau dir den Code an, den wir gerade eingefügt haben. Da siehst du, wo wir überall Klassen zu den HTML-Objekten hinzugefügt haben, um sie in CSS zu referenzieren. Wo würdest du eine Änderung machen, um das Datum in Türkis anzuzeigen? + +Hab keine Angst, etwas mit dieser CSS-Datei herumzuspielen, und versuche, ein paar Dinge zu ändern. Mit CSS herumzuspielen, kann dir helfen zu verstehen, was die verschiedenen Dinge genau machen. Mach dir keine Sorgen, wenn etwas kaputt geht, du kannst deine Änderungen immer rückgängig machen! + +Wir empfehlen die kostenlosen online-Kurse "Basic HTML & HTML5" und "Basic CSS" auf [freeCodeCamp](https://learn.freecodecamp.org/). Sie werden dir helfen, deine Webseiten mit HTML und CSS schöner zu gestalten. + +Bereit für das nächste Kapitel? :) \ No newline at end of file diff --git a/de-DE/deploy/README.md b/de-DE/deploy/README.md new file mode 100644 index 00000000000..f1478c9bd20 --- /dev/null +++ b/de-DE/deploy/README.md @@ -0,0 +1,246 @@ +# Veröffentlichen! + +> **Hinweis:** Durch das folgende Kapitel muss man sich manchmal durchbeißen. Bleib dran und gib nicht auf; die Website zu veröffentlichen, ist ein sehr wichtiger Schritt. Dieses Kapitel ist in der Mitte des Tutorials platziert, damit dir dein Mentor mit dem etwas anspruchsvolleren Vorgang der Veröffentlichung deiner Website helfen kann. Den Rest des Tutorials kannst du dann auch alleine beenden, sollte die Zeit nicht ausreichen. + +Bis jetzt war deine Webseite nur auf deinem Computer verfügbar. Jetzt wirst du lernen wie du sie 'deployst'! Deployen bedeutet, dass du deine Anwendung im Internet veröffentlichst, so dass endlich jeder darauf zugreifen kann. :) + +Wie du schon gelernt hast, muss eine Webseite auf einem Server liegen. Es gibt eine Vielzahl von Hosting (Server)-Anbietern im Internet, wir werden [PythonAnywhere](https://www.pythonanywhere.com/) verwenden. PythonAnywhere ist kostenlos für kleine Anwendungen, die nicht von vielen Besuchern aufgerufen werden. Also erstmal genau das Richtige für dich. + +Als weiteren externen Dienst werden wir [GitHub](https://www.github.com) nutzen, einen "Code Hosting"-Dienst. Es gibt noch andere solcher Dienste, aber die meisten Programmierer haben heute ein Konto bei GitHub, und du auch gleich! + +Diese drei Orte werden für dich wichtig sein. Die Entwicklung und das Testen wirst du auf deinem lokalen Rechner durchführen. Wenn du mit deinen Änderungen zufrieden bist, wirst du eine Kopie deines Programms auf GitHub veröffentlichen. Deine Website wird auf PythonAnywhere gehostet werden. Ändern kannst du sie, indem du eine neue Version deines Codes von GitHub herunter lädst. + +# Git + +> **Hinweis:** Falls du die [Installationsschritte](../installation/README.md) bereits durchgeführt hast, kannst du mit dem nächsten Abschnitt fortfahren und anfangen, dein Git-Repository zu erstellen. + +{% include "/deploy/install_git.md" %} + +## Unser Git-Repository + +Git verwaltet die Veränderungen an einer Sammlung von Dateien in einem sogenannten Repository (oder kurz "Repo"). Legen wir eines für unser Projekt an. Öffne deine Konsole und gibt folgende Kommandos im `djangogirls`-Verzeichnis ein: + +> **Hinweis:** Überprüfe dein aktuelles Arbeitsverzeichnis mit dem Befehl `pwd` (OSX/Linux) oder `cd` (Windows) bevor du das Repository initialisierst. Du musst dich im `djangogirls`-Verzeichnis befinden, bevor du fortfährst. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Dein Name" + $ git config --global user.email du@example.com + + +Die Initialisierung des Git-Repositorys müssen wir für jedes Projekt nur einmal machen (danach musst Du Benutzernamen und Mail-Adresse nie wieder eingeben). + +Git wird die Änderungen an all den Dateien und Ordnern in diesem Verzeichnis aufzeichnen. Wir wollen aber, dass einige Dateien ignoriert werden. Dazu legen wir eine Datei `.gitignore` im Hauptordner (`djangogirls`) des Repos an. Öffne deinen Editor und erstelle eine neue Datei mit dem folgenden Inhalt: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Datenbank + db.sqlite3 + + # Static Ordner im Projektverzeichnis + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +Speichere die Datei mit dem Namen `.gitignore` im "djangogirls"-Root-Verzeichnis. + +> **Hinweis:** Der Punkt vor dem Dateinamen ist wichtig! Wenn du Schwierigkeiten beim Erstellen hast (z.B. lassen Macs im Finder keine Dateien mit Punkt am Anfang erzeugen, Punkt-Dateien sind auf Linux und OS X "versteckte Dateien"), dann verwende die "Speichern unter"-Funktion im Editor, das sollte immer funktionieren. Wichtig ist, dass du den Dateinamen nicht mit `.txt`, `.py` oder einer anderen Dateinamen-Erweiterung ergänzt -- die Datei wird von Git nur erkannt, wenn ihr Name exakt nur `.gitignore` ist. Linux und MacOS behandeln Dateien mit Namen, die mit `.` beginnen (wie `.gitignore`), als versteckt und der normale `ls`-Befehl zeigt diese Dateien nicht an. Verwende stattdessen `ls -a` um die Datei `.gitignore` anzuzeigen. +> +> **Hinweis:** Eine der Dateien, die du in deiner `.gitignore`-Datei defniniert hast, ist `db.sqlite3`. Diese Datei ist deine lokale Datenbank, in welcher alle deine Benutzer und Posts gespeichert werden. Wir werden die gängige Web-Entwicklungs-Praxis befolgen, was heißt, dass wir separate Datenbanken für unsere lokale Test-Website und unsere öffentliche Website auf PythonAnywhere verwenden werden. Die Datenbank für letztere könnte SQLite sein, wie auf deiner Entwicklungsmaschine, aber normalerweise wirst du eine sogenannte MySQL-Datenbank nutzen, welche mit viel mehr Besuchern umgehen kann als SQLite. So oder so, dadurch, dass du deine SQLite-Datenbank für die GitHub-Kopie nicht verwendest, werden alle deine bisherigen Posts der Superuser nur lokal zur Verfügung stehen und du musst in der produktiven Umgebung neue hinzufügen. Betrachte deine lokale Datenbank als tollen Spielplatz, auf welchem du verschiedene Dinge ausprobieren kannst, ohne Angst zu haben, dass du deine wirklichen Post auf deinem Blog löschst. + +Es ist hilfreich den Befehl `git status` vor `git add` auszuführen oder immer dann, wenn du dir unsicher bist, was geändert wurde. Das schützt vor manchen Überraschungen, wie z. B. das falsche Hinzufügen oder Übertragen von Dateien. Das `git status`-Kommando gibt Informationen über unbeobachtete/veränderte/hinzugefügte Dateien, den Status der Verzweigung und einiges mehr wieder. Deine Ausgabe sollte dem hier ähneln: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +Nun speichern wir unsere Änderungen durch folgende Eingabe in der Konsole: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "Meine Django-Girls-App, erster Commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Den Code auf GitHub veröffentlichen + +Gehe auf [GitHub.com](https://www.github.com) eröffne ein neues, kostenloses Nutzerkonto. (Falls Du es bereits während der Workshop-Vorbereitung eingerichtet hast, ist das großartig!) Stelle sicher, dass Du Dein Passwort nicht vergisst (füge es zu zu Deinem Passwort-Manager hinzu, falls Du einen solchen verwendest). + +Erstelle dann ein neues Repository und gib ihm den Namen "my-first-blog". Lass das Kontrollkästchen "initialise with a README" deaktiviert und die Einstellung der Option .gitignore leer (das haben wir schon von Hand gemacht) und lass die Lizenz auf "None". + +![](images/new_github_repo.png) + +> **Achtung:** Der Name `my-first-blog` ist wichtig -- du kannst auch einen anderen wählen, aber er wird im Folgenden noch sehr oft vorkommen und du wirst immer daran denken müssen, ihn in den Anweisungen entsprechend anzupassen. Es ist wahrscheinlich einfacher, bei `my-first-blog` zu bleiben. + +In der nächsten Ansicht wirst du die clone-URL deines Repositorys sehen, die du in manchen der folgenden Kommandozeilenbefehlen verwenden wirst: + +![](images/github_get_repo_url_screenshot.png) + +Nun müssen wir das Git-Repository auf deinem Computer mit dem auf GitHub verbinden. + +Gib das Folgende auf der Kommandozeile ein (ersetzte `` mit dem Benutzernamen, den du beim Erstellen deines GitHub-Accounts gewählt hast, aber ohne die spitzen Klammern -- die URL sollte der clone-URL entsprechen, die du vorhin gerade gesehen hast): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Wenn du zu GitHub pushst, wirst du nach deinem Benutzernamen und Passwort gefragt (entweder direkt im Kommandozeilen-Fenster oder in einem Pop-Up-Fenster), und nach der Eingabe deiner Zugangsdaten solltest du etwas Ähnliches wie das hier sehen: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Dein Code ist jetzt auf GitHub. Schau gleich mal nach! Dort ist dein Code in guter Gesellschaft - [Django](https://github.com/django/django), das [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial) und viele andere großartige Open Source Software-Projekte haben ihren Code auf GitHub. :) + +# Deinen Blog auf PythonAnywhere einrichten + +## Registriere dich für ein PythonAnywhere Konto + +> **Hinweis:** Es ist möglich, dass du bereits ein PythonAnywhere Konto angelegt hast. Wenn ja, dann brauchst du das nicht noch einmal zu tun. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Unsere Site auf PythonAnywhere konfigurieren + +Gehe zurück zum [Haupt-Dashboard PythonAnywhere](https://www.pythonanywhere.com/), indem du auf das Logo klickst. Dann wähle die Option zum Start einer "Bash"-Konsole – die PythonAnywhere Version einer Kommandozeile wie du sie auf deinen Computer hast. + +![Der 'New Console"-Abschnitt auf der PythonAnywhere-Weboberfläche, mit einem Knopf für 'bash'](images/pythonanywhere_bash_console.png) + +> **Hinweis:** PythonAnywhere basiert auf Linux. Wenn du Windows benutzt, dann sieht die Konsole etwas anders aus als die Konsole auf deinem Computer. + +Um eine Web App auf PythonAnywhere publizieren zu können, muss dein Code von GitHub heruntergeladen und PythonAnyhwere dazu gebracht werden, diesen zu erkennen und als Web Applikation anzubieten. Du kannst das auch manuell machen. Aber PythonAnywhere stellt ein Hilfstool zur Verfügung, das das alles für dich erledigt. Lass es uns installieren: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +Nach diesem Befehl solltest du in etwa Folgendes sehen: `Collecting pythonanywhere`, und irgendwann den Schluss `Successfully installed (...) pythonanywhere- (...)`. + +Nun können wir mit dem Hilfstool unsere App von GitHub automatisch konfigurieren. Gib das Folgende in der Konsole auf PythonAnywhere ein (vergiss nicht, deinen GitHub-Benutzernamen an Stelle von `` zu benutzen, so dass die URL der clone-URL von GitHub entspricht): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +Während du die Ausführung verfolgst, wirst du sehen, was passiert: + +- Den Code von GitHub herunterladen +- Eine virtuelle Umgebung auf PythonAnywhere einrichten, genau wie die auf deinem eigenen Computer +- Deine Einstellungen mit ein paar Veröffentlichungseinstellungen aktualisieren +- Eine Datenbank auf PythonAnywhere einrichten mit dem Befehl `manage.py migrate` +- Deine statischen Dateien einrichten (darüber lernen wir später etwas) +- PythonAnywhere so einrichten, dass es deine Web-App über seine Schnittstelle (API) präsentieren kann + +Diese Schritte wurden auf PythonAnywhere automatisiert, aber es sind die selben Schritte, die du bei jedem anderen Server-Provider machen müsstest. + +Das Wichtigste im Moment ist, dass du weißt, dass Deine Datenbank auf PythonAnywhere vollständig unabhängig von deiner Datenbank auf deinem eigenen PC ist, so dass sie unterschiedliche Posts und Administratorenkonten haben kann. Aus diesem Grund müssen wir das Administratorenkonto mittels `createsuperuser` initialisieren - wie wir das auf deinem eigenen Computer getan haben. PythonAnywhere hat deine virtualenv automatisch für dich aktiviert. Du musst nur noch Folgendes ausführen: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Trage die Informationen für deinen Administrator ein. Am Besten verwendest du die selben Daten wie auf deinem eigenen Computer, um Verwechslungen zu vermeiden - es sei denn, du willst das Passwort auf PythonAnywhere sicherer machen. + +Nun kannst auch einen Blick auf deinen Code auf PythonAnywhere werfen mittels `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +Du kannst auch auf die "Files"-Seite gehen und mit PythonAnywheres eingebautem Datei-Manager navigieren. (Von der "Console"-Seite gelangst du über das Menü in der rechten oberen Ecke zu anderen PythonAnywhere-Seiten. Sobald du auf einer dieser Seiten bist, findest du die Links zu den anderen Seiten oben über dem Seiteninhalt.) + +## Du bist jetzt live! + +Nun ist deine Site also live im öffentlichen Internet! Klick dich zur PythonAnywhere "Web"-Seite durch und hole dir den Link. Teile ihn, mit wem du willst. :) + +> **Hinweis:** Da es sich hier um ein Anfänger-Tutorial handelt, haben wir ein paar Abkürzungen genommen, um die Site zu veröffentlichen, welche sicherheitstechnisch nicht ideal sind. Falls du dich entscheidest, dieses Projekt weiterzubauen oder ein neues Projekt anzufangen, dann solltest du die [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) durchgehen, um einige Tipps zur Absicherung deiner Seite zu erhalten. + +## Debugging Tipps + +Solltest du beim Ausführen des `pa_autoconfigure_django.py` Skripts eine Fehlermeldung erhalten, findest du folgend ein paar bekannte Gründe hierfür: + +- Du hast vergessen deinen PythonAnywhere API-Token zu erstellen. +- Du hast in deiner GitHub-URL einen Fehler gemacht. +- Falls du die Fehlermeldung *"Could not find your settings.py"* erhältst, liegt das wahrscheinlich daran, dass du nicht alle Files zum Git hinzugefügt und/oder diese nicht erfolgreich auf GitHub veröffentlicht hast. Schau dir nochmals den Git-Abschnitt weiter oben an. +- Falls du ein bestehendes PythonAnywhere-Benutzerkonto verwendest und eine Fehlermeldung bzgl. collectstatic erhalten hast, hast du dort vermutlich eine alte SQLite-Version (z.B. 3.8.2). Wenn das der Fall ist, erstelle ein neues Benutzerkonto und versuche dort, die Kommandos aus dem obenstehenden PythonAnywhere-Abschnitt erneut auszuführen. + +Falls du eine Fehlermeldung erhältst, wenn du versuchst, deine Site aufzurufen, solltest du als Erstes die Debugging-Informationen im **error log** anschauen. Den Link dazu findest du über [die PythonAnywhere-Seite "Web"](https://www.pythonanywhere.com/web_app_setup/). Schau nach, ob darin Fehlermeldungen enthalten sind; die neuesten findest du ganz unten. + +Du findest einige [Allgemeine Debugging Tipps im PythonAnywhere Wiki](http://help.pythonanywhere.com/pages/DebuggingImportError). + +Und denke daran, dein Coach ist da, um zu helfen! + +# Schau dir deine Website an! + +Auf der Defaultseite deiner Site sollte "It worked!" stehen - genau so wie auf deinem lokalen Computer. Füge nun `/admin/` ans Ende deiner URL an und du kommst auf die Admin-Site. Logge dich mit Benutzername und Passwort ein, und du wirst sehen, dass du auf dem Server neue Posts hinzufügen kannst -- die Posts aus deiner lokalen Test-Datenbank wurden ja nicht auf deinen öffentlichen Blog geschickt. + +Wenn du ein paar Posts erstellt hast, kannst du zurück auf dein lokales Setup (nicht PythonAnywhere) wechseln. Ab jetzt solltest du für Änderungen auf deinem lokalen Setup arbeiten. So wird in der Web-Entwicklung gearbeitet - Änderungen lokal machen und diese dann auf GitHub veröffentlichen und dann deine Änderungen auf den produktiven Webserver ziehen. So kannst du Sachen ausprobieren, ohne deine produktive Website kaputt zu machen. Ziemlich cool, oder? + +Klopf dir *kräftig* auf die Schulter! Server-Deployment ist eines der kompliziertesten Dinge der Web-Entwicklung und es dauert oftmals mehrere Tage, bis alles läuft. Aber du hast deine Site jetzt live, im echten Internet! \ No newline at end of file diff --git a/de-DE/deploy/install_git.md b/de-DE/deploy/install_git.md new file mode 100644 index 00000000000..f6e5cae703d --- /dev/null +++ b/de-DE/deploy/install_git.md @@ -0,0 +1,52 @@ +Git ist ein "Versionsverwaltungssystem" für Dateien und Code, das von vielen Programmierern benutzt wird. Diese Software kann Änderungen an Dateien über die Zeit verfolgen, so dass du bestimmte Versionen im Nachhinein wieder aufrufen kannst. Sie hat Ähnlichkeit mit der Funktion "Änderungen nachverfolgen" in Textverarbeitungsprogrammen (z. B. Microsoft Word oder LibreOffice Writer), ist jedoch weitaus leistungsfähiger. + +## Git installieren + + + +Du kannst Git von [git-scm.com](https://git-scm.com/) herunterladen. Du kannst bei allen Schritten außer zweien "next" klicken: Wähle im Schritt, in dem du einen Editor aussuchen sollst, "Nano"; und bei der Anweisung "Adjusting your PATH environment", wähle die Einstellung "Run Git and associated Unix tools from the Windows command-line" (die letzte Option). Die anderen Voreinstellungen sind ok. "Checkout"-Stil "Windows" und "Commit" mit "Unix line endings" (Zeilenende im Unix-Format) sind die richtigen Einstellungen. + +Vergiss nicht, die Eingabeaufforderung oder PowerShell nach erfolgreicher Installation neu zu starten. + + + +Lade Git von [git-scm.com](https://git-scm.com/) herunter und folge dann den Anweisungen. + +> **Hinweis:** Falls du OS X 10.6, 10.7, oder 10.8 verwendest, muss du die Git-Version unter folgendem Link installieren: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/de-DE/deploy/signup_pythonanywhere.md b/de-DE/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..b94d9d975a9 --- /dev/null +++ b/de-DE/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere ist ein Dienst, mittels dem Python auf Servern "in der Cloud" ausgeführt werden kann. Wir werden ihn verwenden, um unsere Seite zu hosten, live und im Internet. + +Wir werden den Blog, den wir bauen, auf PythonAnywhere hosten. Registriere dich auf PythonAnywhere für ein "Beginner"-Konto (die kostenfreie Stufe ist ausreichend, du brauchst keine Kreditkarte). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![Die PythonAnywhere-Anmelde-Seite mit einem Knopf, um ein kostenloses 'Beginner'-Benutzerkonto anzulegen](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Hinweis** Beachte bei der Wahl deines PythonAnywhere-Benutzernamens, dass die URL deines Blogs die Form `deinbenutzername.pythonanywhere.com` haben wird. Wähle also einen Namen, unter dem du veröffentlichen willst, oder einen Namen, der den Inhalt deines Blogs beschreibt. Und vergiss dein Passwort nicht (füge es deinem Passwortmanager hinzu, wenn du einen benutzt). + +## Erstellen eines PythonAnywhere API-Tokens + +Das Folgende musst du nur einmal machen. Wenn du dich auf PythonAnywhere angemeldet hast, kommst du aufs "Dashboard". Oben rechts findest du den Link zu deiner "Account"-Seite: + +!["Account"-Link oben rechts auf der Seite](../deploy/images/pythonanywhere_account.png) + +Klicke dort auf den Reiter namens "API token" und dann auf den Knopf, der mit "Create new API token" beschriftet ist. + +![Der API-Token-Reiter auf der "Account"-Seite](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/de-DE/django/README.md b/de-DE/django/README.md new file mode 100644 index 00000000000..5238cee1750 --- /dev/null +++ b/de-DE/django/README.md @@ -0,0 +1,27 @@ +# Django - Was ist das? + +Django (*/ˈdʒæŋɡoʊ/*) ist ein freies, quelloffenes Web-Anwendungs-Framework, geschrieben in Python. Ein Web-(Anwendungs-)Framework ist eine Art Baukastensystem, das dir mit vielen vorgefertigten Teilen die Entwicklung von Web-Anwendungen stark erleichtert. + +Wenn du eine Website entwickelst, brauchst du immer wieder sehr ähnliche Elemente: Einen Weg, Benutzer zu verwalten (Registrierung, Anmeldung, Abmeldung etc.), einen Administrationsbereich, Formulare, Upload von Dateien usw. + +Glücklicherweise wurde schon vor einiger Zeit erkannt, dass Web-Entwickler immer wieder die gleichen Probleme zu lösen haben. Gemeinsam entstanden so verschiedene Frameworks (Django ist so eines), welche die Web-Entwicklung durch vorgefertigte Elemente erleichtern. + +Frameworks sind dazu da, damit du das Rad nicht neu erfinden musst. Du kannst dich auf die konkret zu erfüllenden Anforderungen der Webseite kümmern. Die grundlegende Basis der Webseite stellt dir das Framework zur Verfügung. + +## Warum brauchst du ein Framework? + +Um besser zu verstehen, welche Vorteile dir Django bietet, werfen wir einen Blick auf Server im Allgemeinen. Als Erstes muss der Server wissen, dass er eine Webseite ausliefern soll. + +Der Server hat mehrere "Ports". Ein Port ist vergleichbar mit einem Briefkasten, der auf eingehende Briefe ("Anfragen", "requests") überwacht wird. Das macht der Webserver. Der Webserver liest die eingeworfenen Briefe (requests) und beantwortet sie mit der Webseite (response). Um etwas ausliefern zu können, brauchen wir Inhalte. Und Django hilft dir dabei, diese Inhalte zu erstellen. + +## Was passiert, wenn jemand eine Webseite beim Server anfordert? + +Wenn die Anfrage beim Web-Server ankommt, reicht er diese an Django weiter. Und Django versucht herauszufinden, welche Seite genau angefordert wurde. Django wertet zuerst die Adresse der Webseite aus und versucht herauszufinden, was getan werden soll. Dafür ist der **urlresolver** von Django verantwortlich (Hinweis: URL - Uniform Resource Locator ist ein anderer Name für die Web-Adresse, daher der Name *urlresolver*). Sehr schlau ist er aber nicht. Er hat eine Musterliste und vergleicht diese mit der URL. Der Vergleich der Muster erfolgt von oben nach unten. Wenn ein Muster auf die URL zutrifft, wird der damit verknüpften Funktion (der sogenannten *view*) der Request/die Anfrage übergeben. + +Stell dir eine Postbotin mit einem Brief vor. Sie geht die Straße entlang und prüft jede Hausnummer mit der Adresse auf dem Brief. Wenn beide passen, dann steckt sie den Brief in den Briefkasten. So funktioniert der urlresolver! + +In der *view* Funktion passieren all die interessanten Dinge: wir können in eine Datenbank gucken und dort nach Informationen suchen. Vielleicht wollte die Benutzerin irgendetwas in den Daten ändern? So, als ob der Brief sagen würde: "Bitte ändere meine Stellenbeschreibung!" Die Funktion *view* kann nun prüfen, ob du dazu berechtigt bist, im positiven Fall die Änderungen durchführen und im Anschluss eine Bestätigungs-Nachricht zurücksenden. Die *view* generiert dann eine Antwort und Django kann diese an den Webbrowser der Benutzerin senden. + +Die Beschreibung oben ist ein wenig vereinfacht, aber du musst noch nicht all die technischen Details wissen. Eine generelle Vorstellung zu haben, reicht erstmal. + +Anstatt zu sehr ins Detail zu gehen, fangen wir lieber an, mit Django etwas zu erschaffen, und du wirst dabei alles Wichtige lernen! \ No newline at end of file diff --git a/de-DE/django_admin/README.md b/de-DE/django_admin/README.md new file mode 100644 index 00000000000..476448ead45 --- /dev/null +++ b/de-DE/django_admin/README.md @@ -0,0 +1,57 @@ +# Django-Administration + +Wir benutzen den Django-Admin, um die soeben modellierten Posts hinzuzufügen, zu ändern oder zu löschen. + +Öffne die Datei `blog/admin.py` im Code-Editor und ersetze den Inhalt wie folgt: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +Wie du siehst, importieren wir hier das Model "Post", das wir im vorherigen Kapitel erstellt haben. Damit unser Model auf der Admin-Seite sichtbar wird, müssen wir es mit `admin.site.register(Post)` registrieren. + +Okay, wir sehen uns nun unser Post-Model an. Denk daran, `python manage.py runserver` in die Konsole einzugeben, um den Webserver zu starten. Öffne deinen Browser und gib die Adresse http://127.0.0.1:8000/admin/ ein. Du siehst eine Anmeldeseite: + +![Login Seite](images/login_page2.png) + +Um dich einloggen zu können, musst du zunächst einen *superuser* erstellen - einen User, der alles auf der Website steuern darf. Geh zurück zur Kommandozeile, tippe `python manage.py createsuperuser` und drücke Enter. + +> Denke daran, damit du neue Kommandos eingeben kannst während der Webserver läuft, musst du ein neues Terminal öffnen und deine virtualenv aktivieren. Wie man neue Kommandos eingeben kann, haben wir im Kapitel **Dein erstes Django-Projekt!** unter **Den Webserver starten** behandelt. + +{% filename %}Mac OS X oder Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +Wenn du dazu aufgefordert wirst, gib einen Benutzernamen (Kleinbuchstaben, keine Leerzeichen), eine Mailadresse und ein Passwort ein. **Mach dir keine Gedanken, wenn du das Passwort bei der Eingabe nicht sehen kannst - so soll es sein.** Tippe weiter und drücke `Enter`, um weiterzumachen. Du solltest nun Folgendes sehen (wobei Benutzername und Email deine eigenen sein sollten): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Geh nochmal in deinen Browser und log dich mit den Daten des Superusers ein, den du gerade erstellt hast. Du solltest nun das Django-Admin-Dashboard sehen. + +!["Django Admin"-Weboberfläche](images/django_admin3.png) + +Gehe auf Posts und experimentiere ein bisschen damit. Füge fünf oder sechs Blogeinträge hinzu. Mach dir keine Sorgen wegen des Inhalts -- der ist nur auf deinem lokalen Computer sichtbar. Um Zeit zu sparen kannst du etwas Text aus diesem Tutorial kopieren und einfügen. :-) + +Achte darauf, dass bei wenigstens zwei oder drei Posts (aber nicht bei allen) das Veröffentlichungsdatum (publish date) eingetragen ist. Das werden wir später noch brauchen. + +!["Django Admin"-Weboberfläche](images/edit_post3.png) + +Mehr zum Django-Admin-Dashboard kannst du in der Django-Dokumentation erfahren: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +Jetzt ist wahrscheinlich ein guter Moment, um dir einen Kaffee (oder Tee) zu gönnen und neue Kraft zu tanken. Du hast dein erstes Django-Model erstellt - du hast dir eine kleine Pause verdient! \ No newline at end of file diff --git a/de-DE/django_forms/README.md b/de-DE/django_forms/README.md new file mode 100644 index 00000000000..9968e6ea163 --- /dev/null +++ b/de-DE/django_forms/README.md @@ -0,0 +1,478 @@ +# Django-Formulare + +Als Letztes möchten wir auf unserer Website noch die Möglichkeit haben, Blogposts hinzuzufügen und zu editieren. Die Django `admin`-Oberfläche ist cool, aber eher schwierig anzupassen und hübsch zu machen. Mit Formularen, `forms`, haben wir die absolute Kontrolle über unser Interface - wir können fast alles machen, was man sich vorstellen kann! + +Das Gute an Django-Forms ist, dass man sie entweder vollständig selbst definieren oder eine `ModelForm` erstellen kann, welche den Inhalt des Formulars in das Model speichert. + +Genau das wollen wir jetzt machen: Wir erstellen ein Formular für unser `Post`-Model. + +So wie die anderen wichtigen Django-Komponenten haben auch die Forms ihre eigene Datei: `forms.py`. + +Wir erstellen nun eine Datei mit diesem Namen im `blog`-Verzeichnis. + + blog + └── forms.py + + +So, jetzt lass uns diese im Code-Editor öffnen und folgenden Code hinzufügen: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Zuerst müssen wir die Django-Forms importieren (`from django import forms`) und auch unser `Post`-Model (`from .models import Post`). + +Wie du wahrscheinlich schon vermutet hast, `PostForm` ist der Name unseres Formulars. Wir müssen Django mitteilen, dass unser Formular ein `ModelForm` ist (so kann Django ein bisschen für uns zaubern) - `forms.ModelForm` ist dafür verantwortlich. + +Als Nächstes sehen wir uns `class Meta` an, damit sagen wir Django, welches Model benutzt werden soll, um das Formular zu erstellen (`model = Post`). + +Nun können wir bestimmen, welche(s) Feld(er) unser Formular besitzen soll. Wir wollen hier nur den `title` und `text` sichtbar machen - der `author` sollte die Person sein, die gerade eingeloggt ist (Du!) und `created_date` sollte automatisch generiert werden, wenn der Post erstellt wird (also im Code). Stimmt's? + +Und das war's schon! Jetzt müssen wir das Formular nur noch in einem *view* benutzen und im Template darstellen. + +Also erstellen wir hier auch wieder einen Link auf die Seite, eine URL, eine View und ein Template. + +## Link auf eine Seite mit dem Formular + +Bevor wir den Link hinzufügen, benötigen wir einige Icons als Buttons für den Link. Lade für dieses Tutorial [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) herunter und speicher es im Ordner `blog/templates/blog/blog/icons/` + +> Hinweis: Um das SVG-Bild herunterzuladen, öffne das Kontextmenü auf dem Link (normalerweise durch einen Rechtsklick darauf) und wähle "Link speichern unter". Im Dialog, in dem du gefragt wirst, wo du die Datei speichern willst, navigiere zum `djangogirls`-Verzeichnis deines Django-Projekts und innerhalb davon in das Unterverzeichnis `blog/templates/blog/icons/` und speicher die Datei dort. + +Es ist an der Zeit, `blog/templates/blog/base.html` im Code-Editor zu öffnen. Jetzt können wir diese Icon-Datei im Basis-Template wie folgt verwenden. Im `div`-Element innerhalb des `header`-Abschnitts werden wir einen Link vor dem `h1`-Element hinzufügen: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Beachte, dass wir unsere neue View `post_new` nennen wollen. Das [SVG-Icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) wird von [Bootstrap Icons](https://icons.getbootstrap.com/) zur Verfügung gestellt und zeigt ein Seitensymbol mit Pluszeichen an. Wir verwenden eine Django-Template-Direktive namens `include`. Dadurch wird der Inhalt der Datei in das Django-Template eingefügt. Der Web-Browser weiß, wie man diese Art von Inhalt ohne weitere Verarbeitung handhabt. + +> Alle Bootstrap-Icons kannst du [hier herunterladen](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Entpacke die Datei und kopiere alle SVG-Bilddateien in einen neuen Ordner namens `icons` innerhalb von `blog/templates/blog/`. So kannst du auf ein Symbol wie `pencil-fill.svg` mit dem Dateipfad `blog/templates/blog/icons/pencil-fill.svg` zugreifen + +Nach dem Bearbeiten der Zeile sieht deine HTML-Datei so aus: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Nach dem Speichern und Neuladen von http://127.0.0.1:8000 solltest du den bereits bekannten `NoReverseMatch`-Fehler sehen. Ist dem so? Gut! + +## URL + +Wir öffnen `blog/urls.py` im Code-Editor und fügen eine Zeile hinzu: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +Der finale Code sieht dann so aus: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +Nach dem Neuladen der Site sehen wir einen `AttributeError`, weil wir noch keine `post_new`-View eingefügt haben. Fügen wir sie gleich hinzu! + +## Die post_new-View + +Jetzt wird es Zeit, die Datei `blog/views.py` im Code-Editor zu öffnen und die folgenden Zeilen zu den anderen `from` Zeilen hinzuzufügen: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +Und dann unsere *View*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Um ein neues `PostForm` zu erstellen, rufen wir `PostForm()` auf und übergeben es an das Template. Wir kommen gleich nochmal zu dem *View* zurück, aber jetzt erstellen wir schnell ein Template für das Form. + +## Template + +Wir müssen eine Datei `post_edit.html` im Verzeichnis `blog/templates/blog` erstellen und im Code-Editor öffnen. Damit ein Formular funktioniert, benötigen wir einige Dinge: + +* Wir müssen das Formular anzeigen. Wir können das zum Beispiel mit einem einfachen `{{ form.as_p }}` tun. +* Die Zeile oben muss von einem HTML-Formular-Element eingeschlossen werden `...`. +* Wir benötigen einen `Save`-Button. Wir erstellen diesen mit einem HTML-Button: ``. +* Und schließlich fügen wir nach dem öffnenden `
` Tag `{% raw %}{% csrf_token %}{% endraw %}` hinzu. Das ist sehr wichtig, da es deine Formulare sicher macht! Wenn du diesen Teil vergisst, wird sich Django beim Speichern des Formulars beschweren. + +![CSFR Forbidden page](images/csrf2.png) + +Ok, also schauen wir mal, wie der HTML-Code in `post_edit.html` aussehen sollte: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +So, jetzt aktualisieren wir die Seite! Yay! Das Formular wird angezeigt! + +![Neues Formular](images/new_form2.png) + +Aber Moment! Wenn du in das `title`- oder `text`-Feld etwas eintippst und versuchst es zu speichern - was wird wohl passieren? + +Nichts! Wir landen wieder auf der selben Seite und unser Text ist verschwunden... und kein neuer Post wurde hinzugefügt. Was lief denn hier schief? + +Die Antwort ist: nichts. Wir müssen einfach noch etwas mehr Arbeit in unsere *View* stecken. + +## Speichern des Formulars + +Öffne `blog/views.py` erneut im Code-Editor. Derzeit ist alles, was wir in der View `post_new` haben, das hier: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Wenn wir das Formular übermitteln, werden wir zur selben Ansicht weitergeleitet, aber dieses Mal haben wir mehr Daten in `request`, genauer in `request.POST` (der Name hat nichts zu tun mit einem "Blogpost", sondern damit, dass wir Daten "posten"). Erinnerst du dich daran, dass in der HTML-Datei unsere `
` Definition die Variable `method="POST"` hatte? Alle Felder aus dem Formular sind jetzt in `request.POST`. Du solltest `POST` nicht umbenennen (der einzige andere gültige Wert für `method` ist `GET`, wir wollen hier jetzt aber nicht auf den Unterschied eingehen). + +Somit müssen wir uns in unserer *View* mit zwei verschiedenen Situationen befassen: erstens, wenn wir das erste Mal auf die Seite zugreifen und ein leeres Formular wollen und zweitens, wenn wir zur *View* mit allen soeben ausgefüllten Formular-Daten zurück wollen. Wir müssen also eine Bedingung hinzufügen (dafür verwenden wir `if`): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +Es wird Zeit, die Lücken zu füllen `[...]`. Falls die `Methode` `POST` ist, wollen wir das `PostForm` mit Daten vom Formular erstellen. Oder? Das machen wir folgendermaßen: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +Als Nächstes müssen wir testen, ob das Formular korrekt ist (alle benötigten Felder sind ausgefüllt und keine ungültigen Werte werden gespeichert). Wir tun das mit `form.is_valid()`. + +Wir überprüfen also, ob das Formular gültig ist und wenn ja, können wir es speichern! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Im Grunde passieren hier zwei Dinge: Wir speichern das Formular mit `form.save` und wir fügen einen Autor hinzu (da es bislang kein `author` Feld in der `PostForm` gab und dieses Feld notwendig ist). `commit=False` bedeutet, dass wir das `Post` Model noch nicht speichern wollen - wir wollen erst noch den Autor hinzufügen. Meistens wirst du `form.save()` ohne `commit=False` benutzen, aber in diesem Fall müssen wir es so tun. `post.save()` wird die Änderungen sichern (den Autor hinzufügen) und ein neuer Blogpost wurde erstellt! + +Wäre es nicht grossartig, wenn wir direkt zu der `post_detail` Seite des neu erzeugten Blogposts gehen könnten? Um dies zu tun, benötigen wir noch einen zusätzlichen Import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Füge dies direkt am Anfang der Datei hinzu. Jetzt können wir endlich sagen: "Gehe zu der `post_detail` Seite unseres neu erstellten Posts": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` ist der Name der View, zu der wir springen wollen. Erinnerst du dich daran, dass diese *view* einen `pk` benötigt? Um diesen an die View weiterzugeben, benutzen wir `pk=post.pk`, wobei `post` unser neu erstellter Blogpost ist! + +Ok, wir haben jetzt eine ganze Menge geredet, aber du willst bestimmt sehen, wie die gesamte *View* aussieht, richtig? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Schauen wir mal, ob es funktioniert. Gehe zur Seite http://127.0.0.1:8000/post/new/, füge einen `title` und `text` hinzu und speichere es...voilà! Der neue Blogpost wird hinzugefügt und wir werden auf die `post_detail` Seite umgeleitet! + +Du hast vielleicht bemerkt, dass wir das Veröffentlichungsdatum festlegen, bevor wir den Post veröffentlichen. Später werden wir einen *publish button* in **Django Girls Tutorial: Extensions** einführen. + +Das ist genial! + +> Da wir vor Kurzem das Django-Admin-Interface benutzt haben, denkt das System, dass wir noch angemeldet sind. Es gibt einige Situationen, welche dazu führen können, dass wir ausgeloggt werden (Schließen des Browsers, Neustarten der Datenbank etc). Wenn du feststellst, dass du bei dem Erstellen von Posts Fehlermeldungen bekommst, die auf nicht angemeldete Nutzer zurückzuführen sind, dann gehe zur Admin Seite http://127.0.0.1:8000/admin und logge dich erneut ein. Dies wird das Problem vorübergehend lösen. Es gibt eine permanente Lösung dafür, die im Kapitel **Homework: add security to your website!** nach dem Haupttutorial auf dich wartet. + +![Anmeldefehler](images/post_create_error.png) + +## Formularvalidierung + +Jetzt zeigen wir dir, wie cool Django-Formulare sind. Ein Blogpost muss `title`- und `text`-Felder besitzen. In unserem `Post`-Model haben wir (im Gegensatz zu dem `published_date`) nicht festgelegt, dass diese Felder nicht benötigt werden, also nimmt Django standardmäßig an, dass sie definiert werden. + +Versuch, das Formular ohne `title` und `text` zu speichern. Rate, was passieren wird! + +![Formularvalidierung](images/form_validation2.png) + +Django kümmert sich darum sicherzustellen, dass alle Felder in unserem Formular richtig sind. Ist das nicht großartig? + +## "Bearbeiten"-Formular + +Jetzt wissen wir, wie ein neuer Blogpost hinzugefügt wird. Aber was ist, wenn wir einen bereits bestehenden bearbeiten wollen? Das funktioniert so ähnlich wie das, was wir gerade getan haben. Lass uns schnell ein paar wichtige Dinge erstellen. (Falls du etwas nicht verstehst, solltest du deinen Coach fragen oder in den vorherigen Kapiteln nachschlagen, da wir all die Schritte bereits behandelt haben.) + +Lass uns zunächst das Symbol speichern, das den Bearbeiten-Button darstellt. Lade [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) herunter und speichere es in `blog/templates/blog/icons/`. + +Öffne `blog/templates/blog/post_detail.html` im Code-Editor und füge folgenden Code innerhalb des Elements `article` hinzu: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +damit die Vorlage so aussieht: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Öffne `blog/urls.py` im Code-Editor und fügen diese Zeile hinzu: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +Wir werden die Vorlage `blog/templates/blog/post_edit.html` wiederverwenden, daher ist das einzig Fehlende eine neue *View*. + +Öffne `blog/views.py` im Code-Editor und füge ganz am Ende der Datei Folgendes hinzu: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Sieht genauso aus wie unsere `post_new`-View, oder? Aber nicht ganz. Zum einen übergeben wir einen zusätzliche `pk`-Parameter aus `urls`. Und: Wir bekommen das `Post`-Model, welches wir bearbeiten wollen, mit `get_object_or_404(Post, pk=pk)` und wenn wir dann ein Formular erstellen, übergeben wir diesen Post als `instance`, wenn wir das Formular speichern… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +als auch, wenn wir ein Formular mit post zum Editieren öffnen: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +Ok, lass uns mal schauen, ob das funktioniert! Geh auf die `post_detail`-Seite. Dort sollte sich ein Editier-Button in der oberen rechten Ecke befinden: + +![Schaltfläche "Bearbeiten"](images/edit_button2.png) + +Wenn du darauf klickst, siehst du das Formular mit unserem Blogpost: + +!["Bearbeiten"-Formular](images/edit_form2.png) + +Probier doch einmal, den Titel oder den Text zu ändern und die Änderungen zu speichern! + +Herzlichen Glückwunsch! Deine Anwendung nimmt immer mehr Gestalt an! + +Falls du mehr Informationen über Django-Formulare benötigst, solltest du die offizielle Dokumentation lesen: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Sicherheit + +Neue Posts durch Klick auf einen Link zu erstellen ist großartig! Aber im Moment ist jeder, der deine Seite besucht, in der Lage, einen neuen Blogpost zu veröffentlichen, und das ist etwas, was du garantiert nicht willst. Lass es uns so machen, dass der Button für dich angezeigt wird, aber für niemanden sonst. + +Öffne die Datei `blog/templates/blog/base.html` im Code-Editor, finde darin unseren `header` und das Anchor-Element, welches du zuvor eingefügt hast. Es sollte so aussehen: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Wir fügen ein weiteres `{% if %}`-Tag ein, was dafür sorgt, dass der Link nur für angemeldete Nutzer angezeigt wird. Im Moment bist das also nur du! Ändere das ``-Element zu Folgendem: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +Dieses `{% if %}` sorgt dafür, dass der Link nur zu dem Browser geschickt wird, wenn der anfragende Nutzer auch angemeldet ist. Das verhindert das Erzeugen neuer Posts nicht komplett, ist aber ein sehr guter erster Schritt. In der Erweiterungslektion kümmern wir uns ausgiebiger um Sicherheit. + +Erinnerst du dich an den Editier-Button, den wir gerade zu unserer Seite hinzugefügt haben? Wir wollen dort dieselbe Anpassung machen, damit andere Leute keine existierenden Posts verändern können. + +Öffne `blog/templates/blog/post_detail.html` im Code-Editor und finde folgende Zeile: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Ändere es wie folgt: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Da du wahrscheinlich angemeldet bist, wirst du beim Refresh der Seite keinen Veränderung feststellen. Lade jedoch die Seite in einem anderen Browser oder einem Inkognito-Fenster ("In Private" im Windows Edge) und du wirst sehen, dass dieser Link nicht auftaucht und das Icon ebenfalls nicht angezeigt wird! + +## Eins noch: Zeit für das Deployment! + +Mal sehen, ob das alles auch auf PythonAnywhere funktioniert. Zeit für ein weiteres Deployment! + +* Commite als Erstes deinen neuen Code und schiebe ihn auf GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Dann führe Folgendes in der [PythonAnywhere Bash-Konsole](https://www.pythonanywhere.com/consoles/) aus: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Denk daran, `` durch deine tatsächliche PythonAnywhere-Subdomain zu ersetzen - ohne die spitzen Klammern.) + +* Gehe schließlich noch rüber [auf die Seite "Web"](https://www.pythonanywhere.com/web_app_setup/) (benutze den Menü-Knopf in der rechten oberen Ecke der Konsole) und klicke **Reload**. Lade deinen Blog https://subdomain.pythonanywhere.com neu, um die Änderungen zu sehen. + +Und das war's. Glückwunsch! :) \ No newline at end of file diff --git a/de-DE/django_installation/README.md b/de-DE/django_installation/README.md new file mode 100644 index 00000000000..e2fe6b6e527 --- /dev/null +++ b/de-DE/django_installation/README.md @@ -0,0 +1,7 @@ +# Django-Installation + +> **Hinweis** Wenn du ein Chromebook verwendest, überspringe bitte dieses Kapitel und folge den Anweisungen im [Chromebook Setup](../chromebook_setup/README.md). +> +> **Hinweis:** Falls du dich bereits durch die [Installationsschritte](../installation/README.md) gearbeitet hast, gibt es keinen Grund dies erneut zu tun – du kannst direkt zum nächsten Kapitel springen! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/de-DE/django_installation/instructions.md b/de-DE/django_installation/instructions.md new file mode 100644 index 00000000000..dba55f4f989 --- /dev/null +++ b/de-DE/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Ein Teil dieses Kapitels basiert auf den Tutorials von Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Teile dieses Kapitels basieren auf dem [django-marcador Tutorial](http://django-marcador.keimlink.de/) lizenziert unter der Creative Commons Attribution-ShareAlike 4.0 International License. Für das "django-marcador Tutorial" liegt das Urheberrecht bei Markus Zapke-Gründemann et al. + +## Virtuelle Umgebung + +Bevor wir mit der Installation von Django beginnen, lernen wir ein sehr hilfreiches Tool kennen, das uns hilft, unsere Arbeitsumgebung zum Coden sauber zu halten. Es ist möglich, diesen Schritt zu überspringen, aber wir legen ihn dir dennoch besonders ans Herz. Mit dem bestmöglichen Setup zu starten, wird dir in der Zukunft eine Menge Frust ersparen! + +Wir erzeugen eine virtuelle Arbeitsumgebung - ein **virtual environment** oder auch *virtualenv*. Das isoliert die Python-/Django-Setups verschiedener Projekte voneinander. Das bedeutet, dass deine Änderungen an einem Website-Projekt keine anderen Projekte beeinträchtigen, an welchen du sonst noch entwickelst. Klingt nützlich, oder? + +Du musst nur das Verzeichnis festlegen, in dem du das `virtualenv` erstellen willst; zum Beispiel dein Home-Verzeichnis. Auf Windows ist dies `C:\Users\Name` (`Name` ist dein Anmeldename/Login). + +> **HINWEIS:** Stelle auf Windows sicher, dass dieser Verzeichnisname keine Umlaute oder Sonderzeichen enthält. Falls dein Benutzername Umlaute enthält, verwende ein anderes Verzeichnis, zum Beispiel `C:\djangogirls`. + +In diesem Tutorial erstellen wir darin ein neues Verzeichnis `djangogirls`: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +Wir erstellen eine virtuelle Umgebung namens `myvenv`. Das Kommando dazu lautet dann: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +Um ein neues `virtualenv` zu erzeugen, musst du auf der Kommandozeile von Windows `python -m venv myvenv` ausführen. Das wird so aussehen: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +wobei `myvenv` der Name deines `virtualenv` ist. Du kannst auch irgend einen anderen Namen wählen, aber bleibe bei Kleinbuchstaben und verwende keine Leerzeichen, Umlaute oder Sonderzeichen. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +Auf Linux oder OS X kann ein `virtualenv` durch das Ausführen von `python3 -m venv myvenv` erzeugt werden. Das wird so aussehen: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` ist der Name deiner neuen virtuellen Arbeitsumgebung, deines neuen `virtualenv`. Du kannst auch irgend einen anderen Namen wählen, aber bleibe bei Kleinbuchstaben und verwende keine Leerzeichen. Eine Gute Idee ist, den Namen kurz zu halten. Du wirst ihn oft benutzen bzw. eingeben müssen! + +> **Hinweis:** Bei manchen Versionen von Debian/Unbuntu kann folgender Fehler auftreten: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> Falls das auftritt, folge den Anweisungen in der Fehlermeldung und installiere das `python3-venv`-Paket: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **HINWEIS:** In manchen Debian/Ubuntu-Versionen kann das zu folgendem Fehler führen: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Falls das eintritt, verwende stattdessen den `virtualenv`-Befehl. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **HINWEIS:** Wenn du einen Fehler wie +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> erhältst, führe stattdessen Folgendes aus: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Mit der virtuellen Umgebung arbeiten + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Starte deine virtuelle Umgebung, indem du Folgendes eingibst: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. Öffne in diesem Fall eine weitere Windows PowerShell über "Als Administrator ausführen". Versuche dann, das folgende Kommando einzugeben, bevor du das virtualenv noch einmal aktivierst: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> Der Vorteil davon ist, dass du nicht zwischen den Editor-Fenstern und den Kommandozeilen-Fenstern wechseln musst + + + + + +Starte deine virtuelle Umgebung, indem du eingibst: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Der Name `myvenv` muss mit dem von Dir gewählten Namen des `virtualenv` übereinstimmen! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +Du erkennst, dass dein `virtualenv` gestartet ist, wenn du vor der Eingabeaufforderung eine Klammer mit dem Namen deiner Umgebung siehst, `(myvenv)`. + +In deiner neuen virtuellen Umgebung wird automatisch die richtige Version von `python` verwendet. Du kannst also `python` statt `python3` eingeben. + +Ok, jetzt ist die erforderliche Umgebung startklar und wir können endlich Django installieren! + +## Django-Installation {#django} + +Da du nun dein `virtualenv` gestartet hast, kannst du Django installieren. + +Bevor wir damit loslegen, sollten wir jedoch sicherstellen, dass wir die neueste Version von `pip` haben, eine Software, mit Hilfe derer wir Django installieren werden: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Pakete mittels requirements-Datei installieren + +Eine requirements-Datei enthält eine Liste von Abhängigkeiten, die von `pip install` installiert werden sollen: + +Erstelle mit dem zuvor installierten Code-Editor eine Datei namens `requirements.txt` im Verzeichnis `djangogirls/`. Das machst du, indem du eine neue Datei in deinem Code-Editor öffnest und als `requirements.txt` im Ordner `djangogirls/` abspeicherst. Dein Ordner sieht jetzt so aus: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +Schreibe in die Datei `djangogirls/requirements.txt` folgenden Text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Führe nun `pip install -r requirements.txt` aus, um Django zu installieren. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). Ist das der Fall, dann verwende bitte einen anderen Ordner ohne Sonderzeichen, Umlaute oder Leerzeichen. (Vorschlag: `C:\djangogirls`). Erstelle ein neues virtualenv in einem neuen Verzeichnis, lösche danach das alte und wiederhohle den oben genannten Befehl. (Das Verzeichnis des virtualenv zu verschieben funktioniert dabei nicht, da virtualenv absolute Pfade verwendet.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> Falls der pip-Aufruf auf Ubuntu 12.04 zu einer Fehlermeldung führt, rufe `python -m pip install -U --force-reinstall pip` auf, um die Installation von pip im virtualenv zu reparieren. + + + +Das war's! Du bist nun (endlich) bereit, deine erste Django-Anwendung zu starten! \ No newline at end of file diff --git a/de-DE/django_models/README.md b/de-DE/django_models/README.md new file mode 100644 index 00000000000..7aa3e065463 --- /dev/null +++ b/de-DE/django_models/README.md @@ -0,0 +1,201 @@ +# Django-Models + +Wir erstellen jetzt etwas, damit wir alle Posts von unserem Blog speichern können. Aber um das zu tun, müssen wir zunächst über `Objekte` sprechen. + +## Objekte + +Eine Herangehensweise an das Programmieren ist das so genannte `objektorientierte Programmieren`. Die Idee dahinter ist, dass wir Dinge und ihre Interaktionen untereinander modellieren können und nicht alles als langweilige Kette von Programmbefehlen hintereinander aufschreiben müssen. + +Was ist denn nun ein Objekt? Ein Objekt ist eine Sammlung von Eigenschaften und Aktionsmöglichkeiten, das anhand einer Vorlage (Klasse) erstellt wird. Das klingt erst einmal komisch, aber hier haben wir gleich ein Beispiel. + +Wenn wir zum Beispiel eine Katze modellieren wollen, erschaffen wir eine Objektvorlage `Katze`, eine Art Blaupause oder Schema, nach welcher zukünftig jedes spezifische Katzenobjekt erstellt werden kann. Die Vorlage beschreibt typische Eigenschaften von Katzen, z.B. `farbe`, `alter`, `stimmung` (also gut, schlecht oder müde ;)), `besitzerin` (die ein `Person`-Objekt ist oder – im Falle einer Streunerkatze – leer bleibt). + +Jedes Objekt einer `Katze` soll natürlich auch einige Aktionsmöglichkeiten besitzen: `schnurren`, `kratzen` oder `füttern` (hier bekäme die Katze ein bisschen `Katzenfutter`, welches wieder durch ein eigenes Objekt mit Eigenschaften wie `Geschmack` repräsentiert sein könnte). + + Katze + -------- + farbe + alter + stimmung + besitzerin + schnurren() + kratzen() + fuettern(katzen_futter) + + + Katzenfutter + -------- + geschmack + + +Der Gedanke dahinter ist also, echte Dinge mit Hilfe von Eigenschaften (genannt `Objekteigenschaften`) und Aktionsmöglichkeiten (genannt `Methoden`) im Programmcode zu beschreiben. + +Wie also modellieren wir Blogposts? Schließlich wollen wir ja einen Blog bauen, nicht wahr? + +Wir müssen folgende Fragen beantworten: Was ist ein Blogpost? Welche Eigenschaften sollte er haben? + +Nun, zum einen braucht unser Blogpost Text mit einem Inhalt und einen Titel, oder? Außerdem wäre es schön zu wissen, wer ihn geschrieben hat – wir brauchen also noch einen Autor. Schließlich wollen wir wissen, wann der Post geschrieben und veröffentlicht wurde. + + Post + -------- + title + text + author + created_date + published_date + + +Was für Dinge könnte man mit einem Blogpost machen? Es wäre schön, wenn wir eine `Methode` hätten, die den Post veröffentlicht, nicht wahr? + +Wir brauchen also eine `veröffentlichen`-Methode. + +Da wir jetzt wissen, was wir erreichen wollen, können wir nun damit anfangen, es in Django zu formulieren! + +## Ein Django-Model erstellen + +Da wir jetzt in etwa wissen, was ein Objekt ist, wollen wir ein Django-Model, eine Vorlage, für unsere Blogposts anlegen, nach welcher wir zukünftig unsere Blogpostobjekte erstellen können. + +Ein "Modell" ist in Django ein Objekt einer speziellen Sorte – eines das in der `Datenbank` gespeichert wird. Eine Datenbank ist eine Sammlung von Daten. Dies ist ein Ort, an dem du Informationen zu Benutzern, deinen Blogposts usw. speichern wirst. Wir benutzen dafür eine SQLite-Datenbank. Das ist die Voreinstellung in Django – für uns wird das erst einmal ausreichen. + +Du kannst dir ein Model wie eine Tabelle mit Spalten ("Feldern", englisch "fields") und Zeilen (Datensätzen) vorstellen. + +### Eine Applikation für unseren Blog + +Um unsere Webseite aufgeräumt zu halten, werden wir eine eigene Anwendung für unser Projekt erstellen, wir nennen das eine Applikation. Wir wollen uns gleich daran gewöhnen, alles ordentlich und sortiert zu halten. Um eine Applikation zu erstellen, müssen wir das folgende Kommando in der Konsole ausführen (wieder in dem `djangogirls`-Verzeichnis, in dem die `manage.py`-Datei liegt): + +{% filename %}Mac OS X und Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +Wie du sehen kannst, wurde ein neues `blog`-Verzeichnis erstellt, welches schon einige Dateien enthält. Das Verzeichnis und die Dateien unseres Projektes sollten jetzt so aussehen: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +Nach dem Erstellen der Applikation müssen wir Django noch sagen, dass diese auch genutzt werden soll. Das tun wir in der Datei `mysite/settings.py` -- öffne diese in deinem Code-Editor. Wir suchen den Eintrag `INSTALLED_APPS` und fügen darin die Zeile `'blog.apps.BlogConfig',` direkt über der schließenden Klammer `]` ein. Danach sollte es also so aussehen: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Das Blogpost-Model + +Alle `Models` unserer Applikation werden in der `blog/models.py`-Datei definiert. Dies ist also der richtige Platz für unser Blogpost-Model. + +Öffnen wir also `blog/models.py` im Code-Editor, löschen alles darin und schreiben Code wie diesen: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Kontrolliere nochmal, dass du zwei Unterstriche (`__`) vor und hinter dem `str` gesetzt hast. Diese Konvention wird häufig in Python benutzt und manchmal nennen wir es "dunder" (kurz für "double-underscore"). + +Es sieht kompliziert aus, oder? Aber keine Sorge, wir werden erklären, was diese Zeilen bedeuten! + +Die Zeilen, die mit `from` oder `import` beginnen, sind Anweisungen, um Sachen aus anderen Dateien mitzunutzen. Anstatt häufig genutzten Code in jede Datei einzeln zu kopieren, binden wir ihn ein mit: `from... import ...`. + +`class Post(models.Model):` – Diese Zeile definiert unser Model (eine Objekt-Vorlage). + +- `class` ist ein spezielles Schlüsselwort, das angibt, dass wir hier eine Klasse, eine Vorlage für zukünftige Objekte, definieren wollen. +- `Post` ist der Name unseres Models. Wir können ihm auch einen anderen Namen geben (aber wir müssen Sonderzeichen und Leerzeichen vermeiden). Beginne einen Klassennamen immer mit einem Großbuchstaben. +- `models.Model` gibt an, dass das Post-Model ein Django-Model ist, so weiß Django, dass es in der Datenbank gespeichert werden soll. + +Jetzt definieren wir die Eigenschaften, über welche wir gesprochen haben: `title`, `text`, `created_date`, `published_date` und `author`. Um dies zu tun, müssen wir den Typ jedes Felds definieren. (Ist es Text? Eine Zahl? Ein Datum? Eine Beziehung zu einem anderen Objekt, z.B. einem Benutzer?) + +- `models.CharField` – so definierst du ein Textfeld mit einer limitierten Anzahl von Zeichen. +- `models.TextField` – so definierst du ein langes Textfeld ohne Grössenbeschränkung. Klingt doch perfekt für unsere Blogpostinhalte, oder? +- `models.DateTimeField` – ein Feld für einen Zeitpunkt (ein Datum und eine Uhrzeit). +- `models.ForeignKey` – definiert eine Verknüpfung/Beziehung zu einem anderen Model. + +Wir werden nicht den gesamten Code hier erklären, da das zu lange dauern würde. Du solltest einen Blick in die offizielle Django-Dokumentation werfen, wenn du mehr über Modelfelder und darüber wissen möchtest, wie man auch andere Dinge als die oben beschriebenen definiert (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +Was ist mit `def publish(self):`? Das ist genau die `publish`-Methode zum Veröffentlichen unserer Blogposts, über die wir vorher bereits sprachen. `def` zeigt an, dass es sich nachfolgend um eine Funktion/Methode handelt, und `publish` ist der Name der Methode. Du kannst den Namen der Methode auch ändern, wenn du möchtest. Die Benennungsregel ist, dass wir Kleinbuchstaben verwenden, und anstatt Leerzeichen (die in Funktionsnamen nicht vorkommend dürfen) Unterstriche. Eine Methode, die einen Durchschnittspreis berechnet, könnte zum Beispiel `calculate_average_price` genannt werden. + +Oft geben Methoden einen Wert zurück (englisch: `return`). Ein Beispiel dafür ist die Methode `__str__`. In diesem Szenario, wenn wir `__str__()` aufrufen, bekommen wir einen Text (**string**) mit einem Blogpost-Titel zurück. + +Beachte, dass sowohl `def publish(self):` als auch `def __str__(self):` in unserer Klasse eingerückt sind. Mit der Einrückung sagen wir Python, dass diese Methoden Teil der Klasse sind. Ohne die Einrückung wären es für Python Funktionen ausserhalb der Klasse, was zu anderem Verhalten führen würde. + +Wenn dir über Methoden noch etwas nicht klar ist, dann zögere nicht, deinen Coach zu fragen! Wir wissen, dass es kompliziert ist, vor allem, wenn du gleichzeitig lernst, was Objekte und Funktionen sind. Aber hoffentlich sieht es für dich jetzt etwas weniger nach Magie aus! + +### Tabellen für Models in deiner Datenbank erstellen + +Als letzten Schritt wollen wir unser neues Model der Datenbank hinzufügen. Dazu müssen wir Django erst 'mal mitteilen, dass wir einige Änderungen an unserem Model vorgenommen haben. (Wir haben es eben erst erstellt!) Scheibe `python manage.py makemigrations blog` in dein Kommandozeilen-Fenster. Das sieht dann so aus: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Hinweis:** Denke daran, die Dateien nach dem Editieren zu speichern. Ansonsten führt dein Computer die vorherige Version aus, was zu unerwarteten Fehlermeldungen führen kann. + +Django hat eine Migrationsdatei für uns vorbereitet, die wir nun auf unsere Datenbank anwenden müssen. Schreibe `python manage.py migrate blog`. Die Ausgabe sollte so aussehen: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurra! Unser Post-Model ist ab sofort in unserer Datenbank gespeichert! Es wäre doch schön, zu wissen, wie es aussieht, oder? Springe zum nächsten Kapitel, um es dir anzusehen! \ No newline at end of file diff --git a/de-DE/django_orm/README.md b/de-DE/django_orm/README.md new file mode 100644 index 00000000000..6621b90a1d9 --- /dev/null +++ b/de-DE/django_orm/README.md @@ -0,0 +1,219 @@ +# Django-ORM und QuerySets + +In diesem Kapitel lernst du, wie sich Django mit der Datenbank verbindet und Daten darin speichert. Lass uns loslegen! + +## Was ist ein QuerySet? + +Zusammengefasst ist ein QuerySet eine Liste von Objekten eines bestimmten Models. QuerySets erlauben es dir, Daten aus der Datenbank zu lesen, zu filtern und zu sortieren. + +Am besten wir sehen uns das an einem Beispiel an. Versuchen wir's? + +## Django-Shell + +Öffne deine lokale Konsole (nicht in PythonAnywhere) und tippe dieses Kommando ein: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +Das sollte angezeigt werden: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) >>> +``` + +Nun bist du in der interaktiven Konsole von Django. Die funktioniert wie der Python-Prompt, aber hat noch etwas zusätzliche Django-Magie. :) Du kannst hier auch alle Python-Befehle verwenden. + +### Alle Objekte + +Zunächst wollen wir alle unsere Blogposts ansehen. Das kannst du mit folgendem Kommando erreichen: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Hoppla! Eine Fehlermeldung ist erschienen. Sie sagt uns, dass Python "Post" nicht kennt. Und sie hat recht: Wir haben vergessen zu importieren! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +Wir importieren das Model `Post` aus `blog.models`. Versuchen wir nochmal, alle Posts anzuzeigen: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +Das ist eine Liste all der Posts, die wir zuvor lokal erstellt haben! Wir haben diese Posts mit der Django-Admin-Oberfläche erstellt. Aber nun wollen wir weitere Posts mit Python erstellen! Wie geht das also? + +### Objekt erstellen + +So erstellst du ein neues Post-Objekt in der Datenbank: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Allerdings fehlt noch eine Zutat: `me`. Wir müssen eine Instanz des Models `User` als Autor übergeben. Wie macht man das? + +Als Erstes müssen wir das User-Model importieren: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +Welche User sind in unserer Datenbank vorhanden? Finde es damit heraus: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +Das ist der Superuser, den wir vorhin erstellt haben! Lass uns jetzt eine Instanz des Users erstellen (passe diese Zeile an, so dass dein eigener Benutzername verwendet wird): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +Wie du siehst, holen (`get`) wir jetzt ein `User`-Objekt mit einem `username` 'ola'. Prima! + +Jetzt können wir schließlich unseren Post erstellen: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Super! Wollen wir nachsehen, ob es funktioniert hat? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +Da ist er, ein weiterer Post in der Liste! + +### Mehrere Posts hinzufügen + +Du kann jetzt nach Belieben weitere Blogposts hinzufügen, um ein Gefühl dafür zu bekommen, wie es funktioniert. Füge doch noch zwei, drei hinzu bevor du zum nächsten Teil übergehst. + +### Objekte filtern + +Eine wichtige Eigenschaft von QuerySets ist, dass die Einträge gefiltert werden können. Zum Beispiel wollen wir alle Posts finden, die der User Ola geschrieben hat. Dafür nehmen wir `filter` statt `all` in `Post.objects.all()`. In Klammern schreiben wir die Bedingung(en), die ein Blogpost erfüllen muss, damit ein er in unser Queryset kommt. So soll jetzt z.B. `author` gleich `me` sein, damit nur die Blogposts des Autors "me" herausgefiltert werden. In Django schreiben wir deshalb: `author=me`. Jetzt sieht unser Code folgendermaßen aus: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Oder vielleicht wollen wir alle Posts haben, die das Wort "title" im `title`-Feld haben? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Anmerkung:** Zwischen `title` und `contains` befinden sich zwei Unterstriche (`__`). Das ORM von Django nutzt diese Regel, um Feldnamen ("title") und Operationen oder Filter ("contains") voneinander zu trennen. Wenn du nur einen Unterstrich benutzt, bekommst du einen Fehler wie "FieldError: Cannot resolve keyword title_contains". + +Du kannst auch eine Liste aller bereits publizierten Posts erhalten, indem wir nach allen Posts suchen, deren `published_date` in der Vergangenheit liegt: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unglücklicherweise ist der Post, den wir über die Python-Konsole hinzugefügt haben, noch nicht veröffentlicht. Aber das können wir ändern! Als Erstes holen wir eine Instanz des Posts, den wir veröffentlichen wollen: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +Dann publizieren wir ihn mit unserer `publish`-Methode: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Jetzt versuch nochmal, eine Liste von veröffentlichten Posts zu bekommen (drücke dreimal "Pfeil nach oben" und `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Objekte ordnen + +Mit den QuerySets kannst du eine Liste auch nach bestimmten Kriterien ordnen. Lass uns das mit dem `created_date` Feld ausprobieren: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +Wir können die Reihenfolge auch umdrehen, indem wir "`-`" davor schreiben: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Komplexe Queries durch Methoden-Verkettung + +Wie du gesehen hast, geben einige Methoden auf `Post.objects` ein QuerySet zurück. Die selben Methoden können wiederum auch auf einem QuerySet aufgerufen werden und geben dann ein neues QuerySet zurück. Das ermöglicht es, ihre Wirkung zu kombinieren, indem du die Methoden **verkettest**: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +Dies ist wirklich mächtig und lässt dich ziemlich komplexe Abfragen schreiben. + +Cool! Jetzt bist du bereit für den nächsten Teil! Um die Konsole zu schließen, schreib das: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +``` \ No newline at end of file diff --git a/de-DE/django_start_project/README.md b/de-DE/django_start_project/README.md new file mode 100644 index 00000000000..737db5e3a8c --- /dev/null +++ b/de-DE/django_start_project/README.md @@ -0,0 +1,260 @@ +# Dein erstes Django-Projekt! + +> Ein Teil dieses Kapitels basiert auf Tutorials der Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Teile dieses Kapitels basieren auf dem [django-marcador Tutorial](http://django-marcador.keimlink.de/) lizenziert unter Creative Commons Attribution-ShareAlike 4.0 International License. Für das "django-marcador Tutorial" liegt das Urheberrecht bei Markus Zapke-Gründemann et al. + +Wir werden einen kleinen Blog erstellen! + +Der erste Schritt ist, ein neues Django-Projekt zu starten. Im Grunde bedeutet das, dass wir einige Skripte ausführen werden, die Django zur Verfügung stellt, um ein Skelett eines Django-Projekts für uns zu erzeugen. Das Projekt beinhaltet einen Haufen von Verzeichnissen und Dateien, die wir später verwenden werden. + +Die Namen einiger Dateien und Verzeichnisse sind sehr wichtig für Django. Die Dateien, die erstellt werden, solltest du nicht umbenennen. Sie an eine andere Stelle zu verschieben, ist auch keine gute Idee. Django muss zwingend eine gewisse Struktur erhalten, um wichtige Dinge wiederzufinden. + +> Denk daran, alles in der "Virtualenv"-Umgebung auszuführen. Wenn du kein Präfix `(myvenv)` in deiner Konsole siehst, musst du deine Virtualenv-Umgebung aktivieren. Wie das gemacht wird, erklären wir im Kapitel **Django-Installation**, im Abschnitt **Arbeiten mit Virtualenv**. Zur Erinnerung: Gib dazu auf Windows `myvenv\Scripts\activate` ein, bzw. auf OS X oder Linux `source myvenv/bin/activate`. + + + +In deiner OS X- oder Linux-Konsole solltest du den folgenden Befehl ausführen; **vergiss den Punkt (`.`) am Ende nicht!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> Der Punkt `.` ist sehr wichtig, weil er dem Skript mitteilt, dass Django in deinem aktuellen Verzeichnis installiert werden soll. (Der Punkt `.` ist eine Schnellreferenz dafür.) +> +> **Hinweis:** Wenn du das oben angegebene Kommando eingibst, denk daran, nur das einzutippen, was mit `django-admin` anfängt. Der `(myvenv) ~/djangogirls$`-Teil hier ist nur ein Beispiel für die Eingabeaufforderung (den "Prompt") auf der Kommandozeile. + + + + + +Auf Windows solltest du den folgenden Befehl ausführen. **(Vergiss den Punkt (`.`) am Ende nicht!)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> Der Punkt `.` ist sehr wichtig, weil er dem Skript mitteilt, dass Django in deinem aktuellen Verzeichnis installiert werden soll. (Der Punkt `.` ist eine Schnellreferenz dafür.) +> +> **Hinweis:** Wenn du das oben angegebene Kommando eingibst, denk daran, nur das einzutippen, was mit `django-admin.exe` anfängt. Der `(myvenv) C:\Users\Name\djangogirls>`-Teil hier ist nur ein Beispiel für die Eingabeaufforderung (den "Prompt") auf der Kommandozeile. + + + +`django-admin.py` ist ein Skript, welches Verzeichnisse und Dateien für dich erstellt. Du solltest jetzt eine Verzeichnisstruktur haben, die folgendermaßen aussieht: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Hinweis:** In deiner Verzeichnisstruktur wirst du auch den `venv`-Ordner sehen, den wir vorhin erzeugt haben. + +`manage.py` ist ein Script, das das Management deines Projektes unterstützt. Mit dem Script bist du unter anderem in der Lage, den Webserver auf deinem Rechner zu starten, ohne etwas Weiteres installieren zu müssen. + +Die Datei `settings.py` beinhaltet die Konfiguration deiner Website. + +Erinnerst du dich, als wir über den Postboten gesprochen haben, der überlegt, wohin er den Brief liefern soll? Die `urls.py` Datei beinhaltet eine Liste von Patterns (Mustern), die vom `urlresolver` benutzt werden. + +Lass uns kurz die anderen Dateien vergessen - wir werden sie nicht verändern. Denk aber dran, sie nicht versehentlich zu löschen! + +## Einstellungen anpassen + +Wir machen nun ein paar Änderungen in `mysite/settings.py`. Öffne die Datei mit dem Code-Editor, den du schon installiert hast. + +**Hinweis**: `settings.py` ist eine Datei wie jede andere. Du kannst sie aus deinem Code-Editor heraus öffnen, in dem du im "Datei"-Menü die "Öffnen"-Aktion wählst. So solltest du das normale Fenster zur Dateiauswahl bekommen, in dem du zur `settings.py`-Datei navigieren und sie auswählen kannst. Stattdessen kannst du die Datei aber auch öffnen, in dem du im Dateimanager zum "djangogirls"-Ordner navigierst und auf die Datei rechtsklickst. Wähle dann deinen Code-Editor aus der Liste der "Öffnen mit"-Programme. Das ist wichtig, da du andere Programme installiert haben könntest, die diese Datei zwar öffnen können, aber die dich die Datei nicht editieren lassen würden. + +Es wäre schön, wenn die richtige Zeit auf deiner Webseite eingestellt ist. Gehe zur [Zeitzonen-Liste auf Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) und kopiere die für dich geltende Zeitzone (Spalte "TZ"), z.B. `Europe/Berlin`. + +Suche in `settings.py` die Zeile, die `TIME_ZONE` enthält und ändere sie ab, um deine eigene Zeitzone auszuwählen. Zum Beispiel: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +Ein Sprachkennung besteht aus einem Kürzel für die Sprache, z.B. `en` für Englisch oder `de` für Deutsch, und einem Länder-Kürzel z.B. `de` für Deutschland oder `ch` für die Schweiz. Falls Englisch nicht deine Muttersprache ist, kannst du damit die Standard-Knöpfe und -Meldungen von Django auf deine Sprache wechseln. Der "Cancel"-Knopf würde dann in diese Sprache übersetzt (und z.B. bei Deutsch mit "Abbrechen" beschriftet). [Django enthält viele fix-fertige Übsersetzungen](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +Wenn du eine andere Sprache als Englisch willst, ändere die Sprachkennung, indem du die folgende Zeile änderst: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +Ausserdem müssen wir einen Pfad für statische Dateien festlegen. (Über statische Dateien und CSS lernst du später in diesem Tutorial etwas.) Geh hinunter zum *Ende* der Datei und füge direkt unter dem `STATIC_URL`-Eintrag einen neuen Eintrag namens `STATIC_ROOT` ein: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +Wenn `DEBUG` auf `True` gesetzt ist und `ALLOWED_HOSTS` leer, dann wird der "Host" gegen `['localhost', '127.0.0.1', '[::1]']` validiert. Unser Hostname auf PythonAnywhere, wo wir unsere Anwendung deployen werden, würde da nicht passen. Deswegen ändern wir folgende Einstellung: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Hinweis**: Wenn du ein Chromebook verwendest, füge noch diese Zeile am Ende deiner settings.py-Datei hinzu: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Falls du Cloud9 benutzt, füge auch `.amazonaws.com` zu den `ALLOWED_HOSTS` hinzu +> +> Wenn du dein Projekt auf `Glitch.com` hostest, dann lass uns den Django-Sekret-Key schützen, der vertraulich bleiben muss (andernfalls könnte jeder, der dein Projekt remixt, diesen sehen): +> +> - Zuerst erstellen wir einen zufälligen geheimen Schlüssel. Öffne erneut das Glitch-Terminal und gib den folgenden Befehl ein: +> +> {% filename %}Kommandozeile{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> Das sollte einen langen zufälligen String ausgeben, der perfekt für die Verwendung als geheimer Schlüssel für deine brandneue Django-Website geeignet ist. Wir werden diesen Schlüssel jetzt in eine Datei namens `.env` einfügen, die Glitch nur dir als Besitzerin der Website anzeigen wird. +> +> - Erstelle eine Datei namens `.env` im Wurzelverzeichnis deines Projekts und füge folgenden Inhalt ein: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Hier, innerhalb der einfachen Anführungszeichen, kannst den oben erzeugten zufälligen Schlüssel einfügen +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Aktualisiere dann die Django-Einstellungen-Datei, um diesen geheimen Wert einzufügen zu lassen und lege den Django-Webseitennamen fest: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - Und etwas weiter unten in derselben Datei geben wir den Namen deiner neuen Glitch-Website ein: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> Der Wert `PROJECT_DOMAIN` wird automatisch von Glitch generiert. Er wird dem Namen deines Projekts entsprechen. + +## Eine Datenbank erstellen + +Es gibt viele verschiedene Datenbank Programme, welche die Daten unserer Website verwalten können. Wir werden die Standard-Datenbanksoftware nehmen, `sqlite3`. + +Das sollte schon in der `mysite/settings.py`-Datei eingestellt sein: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +Um eine Datenbank für unseren Blog zu erstellen, müssen wir folgenden Befehl in der Konsole ausführen (Dazu müssen wir in dem `djangogirls`-Verzeichnis sein, in dem sich auch die `manage.py`-Datei befindet). Wenn alles glatt läuft, sollte das so aussehen: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +Und wir sind fertig! Zeit, unseren Webserver zu starten, um zu sehen, ob unsere Website funktioniert! + +## Den Webserver starten + +Kontrolliere, dass du in dem Verzeichnis bist, in dem die `manage.py`-Datei liegt (das `djangogirls`-Verzeichnis). Wir starten den Webserver, indem wir in der Konsole `python manage.py runserver` ausführen: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Wenn du ein Chromebook verwendest, benutze stattdessen diesen Befehl: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +oder wenn du Glitch verwendest, diesen: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +Wenn du Windows benutzt und dies mit dem `UnicodeDecodeError` fehlschläft, verwende diesen Befehl: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Jetzt wollen wir schauen, ob unsere Website funktioniert: Öffne deinen Browser (Firefox, Chrome, Safari, Edge oder was du sonst nutzt) und gib diese Adresse ein: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +Wenn du ein Chromebook und Cloud9 verwendest, dann klicke stattdessen die URL im erschienenen Fenster in der oberen rechten Ecke des Kommandozeilenfensters, in dem der Webserver läuft. Die URL sollte etwa so aussehen: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +oder auf Glitch: + + https://name-deines-glitch-projects.glitch.me + + +Glückwunsch! Du hast gerade deine erste Website erstellt und sie auf deinem Webserver laufen! Ist das nicht toll? + +![Installation hat funktioniert!](images/install_worked.png) + +Beachte, dass ein Terminalfenster immer nur eine Sache zur selben Zeit erledigen kann, und in dem Terminalfenster, was du vorhin geöffnet hast, läuft gerade der Webserver. Und solange der Webserver läuft und auf einkommende Anfragen wartet, akzeptiert das Terminal zwar Texteingaben, aber es wird keine neuen Befehle ausführen. + +> Wie Webserver funktionieren, haben wir im Kapitel **"Wie das Internet funktioniert"** angesehen. + +Um weitere Kommandos einzugeben, während der Webserver läuft, öffne ein neues Kommandozeilen-Fenster und aktiviere dort deine Virtualenv-Umgebung. Siehe [Einführung in die Kommandozeile](../intro_to_command_line/README.md), um nachzulesen, wie du ein zweites Kommandozeilen-Fenster öffnen kannst. Um den Webserver zu stoppen, wechsel zurück in das Fenster, in dem er läuft, und drücke STRG+C - Steuerung und C gleichzeitig. (In Windows kann es sein, dass du STRG und "Pause"-Taste drücken musst). + +Bereit für den nächsten Schritt? Es wird Zeit, ein paar Inhalte hinzuzufügen! \ No newline at end of file diff --git a/de-DE/django_templates/README.md b/de-DE/django_templates/README.md new file mode 100644 index 00000000000..470a6e09043 --- /dev/null +++ b/de-DE/django_templates/README.md @@ -0,0 +1,108 @@ +# Django-Templates + +Es wird Zeit, ein paar Daten anzuzeigen! Django bringt dafür bereits ein paar sehr hilfreiche **Template-Tags** mit. + +## Was sind Template-Tags? + +Also, in HTML kann man nicht wirklich Python-Code schreiben, weil es der Browser nicht verstehen würde. Denn der kennt nur HTML. Wir wissen, dass HTML ziemlich statisch ist, während Python dynamischer ist. + +Die **Django-Template-Tags** erlauben uns, Python-artige Dinge ins HTML zu bringen, so dass man einfach und schnell dynamische Websites erstellen kann. Super! + +## Anzeigen des Post-List-Templates + +Im vorangegangen Kapitel haben wir unserem Template in der `posts`-Variable eine Liste von Posts übergeben. Diese wollen wir jetzt in HTML anzeigen. + +Um eine Variable in einem Django-Template darzustellen, nutzen wir doppelte, geschweifte Klammern mit dem Namen der Variable darin, so wie hier: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Versuche das in deinem `blog/templates/blog/post_list.html` Template. Öffne es in deinem Code-Editor und ersetze alles vom zweiten `
` bis zum dritten `
` mit `{{ posts }}`. Speichere die Datei und aktualisiere die Seite, um die Ergebnisse anzuzeigen. + +![Abbildung 13.1](images/step1.png) + +Wie du siehst, haben wir nun das: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +Das heißt, Django versteht es als Liste von Objekten. Kannst du dich noch an die Einführung von Python erinnern, wie man Listen anzeigen kann? Ja, mit for-Schleifen! In einem Django-Template benutzt du sie so: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +    {{ post }} +{% endfor %} +``` + +Versuch das in deinem Template. + +![Abbildung 13.2](images/step2.png) + +Es funktioniert! Aber wir wollen, dass die Posts so wie die statischen Posts angezeigt werden, die wir vorhin im **Einführung in HTML**-Kapitel erstellt haben. Du kannst HTML und Template Tags mischen. Unser `body` sollte dann so aussehen: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Alles, was du zwischen `{% for %}`und `{% endfor %}` schreibst, wird für jedes Objekt in der Liste wiederholt. Aktualisiere deine Seite:{% endraw %} + +![Abbildung 13.3](images/step3.png) + +Ist dir aufgefallen, dass wir diesmal eine etwas andere Notation benutzen haben (`{{ post.title }}` oder `{{ post.text }}`)? Wir greifen auf Daten von jedem Feld unseres `Post`-Models zu. Außerdem leitet das `|linebreaksbr` den Text der Posts durch einen Filter, um Zeilenumbrüche in Absätze umzuwandeln. + +## Und zum Schluss + +Es wäre gut zu sehen, ob deine Website noch immer im öffentlichen Internet funktioniert, richtig? Lass uns versuchen, unsere Aktualisierungen wieder zu PythonAnywhere hochzuladen. Hier ist eine Zusammenfassung der Schritte… + +* Schiebe zuerst deinen Code auf GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Dann logg dich wieder bei [PythonAnywhere](https://www.pythonanywhere.com/consoles/) ein, geh zu deiner **Bash-Konsole** (oder starte eine neue) und gib ein: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Denk daran, `` durch deine tatsächliche PythonAnywhere-Subdomain zu ersetzen - ohne die spitzen Klammern.) + +* Spring anschließend rüber zur [Seite "Web"](https://www.pythonanywhere.com/web_app_setup/) und klick auf **Neu laden** in deinem Browser. (Um von der Konsolen-Seite aus zu anderen PythonAnywhere-Seiten zu gelangen, benutze den Menü-Knopf in der rechten oberen Ecke.) Ein Update sollte auf https://subdomain.pythonanywhere.com live sein -- guck's dir im Browser an! Wenn die Blogposts auf deiner PythonAnywhere-Seite anders sind als die auf deinem lokalen Server, ist das in Ordnung so. Die Datenbanken auf deinem lokalen Computer und auf PythonAnywhere werden nicht zusammen mit den restlichen Dateien abgeglichen. + +Glückwunsch! Nun kannst du dich daran machen, neue Posts in deinem Django Admin zu erstellen (denk daran, auch ein published_date einzufügen!). Stell sicher, dass du im Django-Admin der PythonAnywhere-Seite https://subdomain.pythonanywhere.com/admin arbeitest. Dann aktualisiere die Seite und schau nach, ob die Posts dort erscheinen. + +Funktioniert super? Wir sind so stolz auf dich! Steh kurz auf und geh ein Stück weg vom Computer. Du hast dir eine Pause verdient :) + +![Abbildung 13.4](images/donut.png) \ No newline at end of file diff --git a/de-DE/django_urls/README.md b/de-DE/django_urls/README.md new file mode 100644 index 00000000000..728b50c8461 --- /dev/null +++ b/de-DE/django_urls/README.md @@ -0,0 +1,103 @@ +# Django-URLs + +Gleich werden wir unsere erste Website basteln: eine Homepage für deinen Blog! Zuerst sollten wir uns jedoch mit Django URLs beschäftigen. + +## Was ist eine URL? + +Eine URL ist eine Web-Adresse. Jedes Mal, wenn du eine Website besuchst, kannst du eine URL sehen - sie ist in der Adressleiste des Browsers sichtbar. (Ja! `127.0.0.1:8000` ist eine URL! Und `https://djangogirls.org` ist auch eine URL.) + +![URL](images/url.png) + +Jede Seite im Internet braucht ihre eigene URL. Dadurch weiß deine Applikation, was sie dem Nutzer, der eine URL öffnet, zeigen soll. In Django verwenden wir eine sogenannte `URLconf` (URL-Konfiguration). URLconf ist eine Ansammlung von Mustern, die Django mit der empfangenen URL abgleicht, um die richtige View zu finden, das heißt, um letztlich die richtige Seite für den Nutzer anzuzeigen. + +## Wie funktionieren URLs in Django? + +Öffne die `mysite/urls.py`-Datei in deinem Code-Editor nach Wahl und schaue dir an, wie sie aussieht: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +Wie du siehst, hat Django hier schon etwas für uns eingefügt. + +Zeilen zwischen dreifachen Gänsefüßchen (`'''` oder `"""`) heißen Docstrings (Kommentare) - man kann sie am Anfang der Datei, Klasse oder Methode platzieren, um zu beschreiben, was sie tut. Sie werden von Python nicht ausgeführt. + +Die admin-URL, die du im vorangegangenen Kapitel bereits besucht hast, ist schon da: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +Diese Zeile bedeutet, dass Django für jede URL, die mit `admin/` beginnt, die entsprechende *View* finden wird. Hier wird mit admin-site.urls eine ganze Sammlung von admin-URLs referenziert. Dadurch müssen nicht alle in dieser kleinen Datei aufgeführt werden und sie bleibt lesbarer und übersichtlicher. + +## Deine erste Django-URL! + +Es wird Zeit, unsere erste URL zu erstellen! Wir wollen, dass 'http://127.0.0.1:8000/' die Homepage unseres Blogs wird und eine Liste unserer Posts zeigt. + +Wir wollen auch, dass die `mysite/urls.py`-Datei sauber bleibt. Deshalb importieren wir die URLs unserer `Blog`-Applikation in die `mysite/urls.py`-Hauptdatei. + +Also los: Füge eine Zeile hinzu, die `blog.urls` importiert. Ausserdem wirst du die Zeile `from django.urls…` ändern müssen, da wir hier die Funktion `include` verwenden, die du in dieser Zeile noch importieren musst. + +Deine `mysite/urls.py`-Datei sollte jetzt so aussehen: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django wird nun alle Aufrufe von 'http://127.0.0.1:8000/' auf `blog.urls` umleiten und dort nach weiteren Anweisungen schauen. + +## blog.urls + +Erstelle eine neue leere Datei namens `urls.py` im Verzeichnis `blog` und öffne sie im Code-Editor. Alles klar! Füge folgende zwei Zeilen ein: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Hier importieren wir die Django-Funktion `path` und alle unsere `views` aus unserer `blog`-Applikation. (Wir haben noch keine, aber dazu kommen wir gleich!) + +Jetzt können wir unser erstes URL-Muster hinzufügen: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +Wie du siehst, fügen wir nun eine `view` mit dem Namen `post_list` zur Root-URL hinzu. Leere Zeichenfolgen passen auf dieses Muster und der Django-URL-Resolver ignoriert den Domain-Namen (z.B. http://127.0.0.1:8000/), der im vollständigen Pfad voransteht. Dieses Muster sagt Django also, dass `views.post_list` das gewünschte Ziel ist, wenn jemand deine Website über 'http://127.0.0.1:8000/' aufruft. + +Der letzte Teil `name='post_list'` ist der Name der URL, der genutzt wird, um die View zu identifizieren. Er kann identisch mit dem Namen der View sein, aber es kann auch ein komplett anderer sein. Wir werden später die Namen der URLs im Projekt benutzen. Daher ist es wichtig, jede URL in der App zu benennen. Wir sollten außerdem versuchen, eindeutige und einfach zu merkende URL-Namen zu wählen. + +Wenn du jetzt versuchst, http://127.0.0.1:8000/ aufzurufen, dann erscheint eine Meldung der Art "Webseite nicht verfügbar". Das erscheint deshalb, weil der Server nicht mehr läuft. (Erinnerst du dich noch, `runserver` eingegeben zu haben?) Schau mal in deiner Server-Konsole nach und finde heraus, warum der Server nicht mehr läuft. + +![Error](images/error1.png) + +Die Konsole zeigt einen Fehler, aber keine Sorge – der ist eigentlich ziemlich nützlich: Er sagt dir, dass **kein Attribut 'post_list'** vorhanden ist. Das ist der Name der *View*, die Django zu finden und zu verwenden versucht, aber wir haben sie noch gar nicht erstellt. In diesem Zustand wird dein `/admin/` auch nicht funktionieren. Keine Sorge, das regeln wir gleich. Wenn du eine andere Fehlermeldung siehst, versuche es nochmal nach einem Neustart des Webservers. Stoppe dazu den Webserver, indem du Strg+C drückst (die Strg- bzw. Ctrl- und die C-Taste zusammen). Auf Windows musst du evtl. Strg+Untbr (bzw. Ctrl+Break) drücken. Dann musst du den Webserver mittels des Kommandos `python manage.py runserver` erneut starten. + +> Wenn du mehr über Django-URLconfs lernen willst, dann öffne die offizielle Dokumentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/de-DE/django_views/README.md b/de-DE/django_views/README.md new file mode 100644 index 00000000000..ac71c660d35 --- /dev/null +++ b/de-DE/django_views/README.md @@ -0,0 +1,44 @@ +# Django-Views - leg los! + +Es wird jetzt Zeit, den Bug, den wir im letzten Kapitel erzeugt haben, zu beheben! :) + +In der *View* schreiben wir die Logik unserer Anwendung. So werden Informationen aus dem `Model` abgefragt werden, welches du zuvor erzeugt hast und diese werden an ein `Template` weitergeben. Ein Template erzeugen wir im nächsten Kapitel. Views sind Python-Funktionen, die ein bisschen komplizierter sind als die, die wir im Kapitel **Einführung in Python** kennengelernt haben. + +Views kommen in die `views.py` Datei. Wir fügen nun also unsere *Views* zur Datei `blog/views.py` hinzu. + +## blog/views.py + +OK, wir öffnen jetzt diese Datei in unserem Code-Editor und schauen, was darin steht: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +OK, hier steht noch nicht so viel. + +Denk daran, Zeilen mit einem `#` am Anfang sind Kommentare – das bedeutet, dass diese Zeilen von Python nicht ausgeführt werden. + +Lass uns eine *View* erstellen, wie der Kommentar das vorschlägt. Füge die folgende Mini-View unter dem Kommentar ein: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Wie du siehst, definieren wir eine Funktion (`def`) mit dem Namen `post_list`, die den Parameter `request` entgegen nimmt und die mit `return` den Rückgabewert einer anderen Funktion namens `render` zurück gibt. Letztere wird unser Template `blog/post_list.html` "rendern" (zu einer fertigen HTML-Seite zusammensetzen). + +Speichere die Datei, öffne http://127.0.0.1:8000/ im Browser und schau nach, was wir jetzt haben. + +Einen anderen Fehler! Lies, was da jetzt los ist: + +![Error](images/error.png) + +Das zeigt, dass der Server zumindest wieder läuft, aber es sieht immer noch nicht richtig aus, oder? Mach dir keine Sorgen, es ist nur eine Fehlerseite, nichts zu befürchten! Genau wie die Fehlermeldungen in der Konsole sind auch die hier ziemlich nützlich. Du erhältst den Hinweis *TemplateDoesNotExist*, also dass es das Template nicht gibt. Lass uns diesen Bug beheben, indem wir im nächsten Kapitel ein Template erstellen! + +> Erfahre mehr über Django Views in der offiziellen Dokumentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/de-DE/dynamic_data_in_templates/README.md b/de-DE/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..4af9e9bf509 --- /dev/null +++ b/de-DE/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamische Daten in Templates + +Wir haben nun schon einige Dinge an verschiedenen Orten fertiggestellt: das `Post`-Model ist in der `models.py` definiert, wir haben die `post_list` in der `views.py` und das Template hinzugefügt. Aber wie schaffen wir es nun, dass unsere Posts wirklich im HTML-Template erscheinen? Denn wir wollen ja erreichen, dass bestimmte Inhalte (die in der Datenbank gespeicherten Models) auf schöne Weise in unserem Template anzeigt werden, richtig? + +Genau dafür sind die *Views* zuständig: die Verbindung zwischen den Models und den Templates. In unserer `post_list`-View müssen wir die Models, die wir anzeigen wollen, hernehmen und diese dem Template übergeben. In einer *View* entscheiden wir, was (welches Model) wir in einem Template anzeigen werden. + +Okay, und wie machen wir das jetzt? + +Wir öffnen unsere Datei `blog/views.py` in unserem Code-Editor. Bisher sieht unsere `post_list`-*View* folgendermaßen aus: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Erinnerst du dich, als wir davon gesprochen haben, dass wir den Code in verschiedene Dateien einfügen müssen? Jetzt ist es an der Zeit, das Model, dass wir in `models.py` beschrieben haben, einzufügen. Wir fügen den Befehl `from .models import Post` folgendermaßen ein: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +Der Punkt vor `models` bedeutet *aktuelles Verzeichnis* oder *aktuelle Anwendung*. Die Dateien `views.py` und `models.py` liegen im selben Verzeichnis. Deswegen können wir `.` und den Namen der Datei (ohne `.py`) benutzen. Dann ergänzen wir für den Import den Namen des Models (`Post`). + +Und nun? Um vom `Post`-Model die tatsächlichen Blogposts zu erhalten, brauchen wir etwas, das `QuerySet` heißt. + +## QuerySet + +Dir sollte schon ungefähr klar sein, wie QuerySets funktionieren. Wir haben darüber im Kapitel [Django-ORM und QuerySets](../django_orm/README.md) gesprochen. + +Wir wollen nun also eine Liste von publizierten Blogposts ausgeben, sortiert nach dem `published_date`, oder? Das haben wir bereits im Kapitel QuerySets gemacht! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Öffnen wir also die Datei `blog/views.py` im Code-Editor und setzen wir dieses Stück Code in die Funktion `def post_list(request)` ein. Aber vergiss nicht, zuerst `from django.utils import timezone` hinzufügen: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +Um unser QuerySet auf der Blogpost-Liste unseres Blogs anzuzeigen, bleiben noch zwei Dinge zu tun: + +1. Das QuerySet `posts` dem Template-Kontext übergeben, in dem wir den `render`-Funktionsaufruf ändern. Das werden wir jetzt tun. +2. Das Template abändern, um das QuerySet `posts` anzuzeigen. Das werden wir in einem späteren Kapitel behandeln. + +Beachte, dass wir eine *Variable* für unser QuerySet erstellt haben: `posts`. Das ist sozusagen der Name unseres QuerySets. Ab jetzt bezeichnen wir das QuerySet mit diesem Namen. + +In der `render`-Funktion haben wir einen Parameter `request` (also alles, was wir vom User über das Internet bekommen) und einen weiteren Parameter, der den Template-Namen (`'blog/post_list.html'`) angibt. Der letzte Parameter, `{}`, ist eine Stelle, in der wir weitere Dinge hinzufügen können, die das Template dann benutzen kann. Wir müssen diesen einen Namen geben (wir verwenden einfach wieder `'posts'`). :) Es sollte nun so aussehen: `{'posts': posts}`. Bitte achte darauf, dass der Teil vor `:` ein String ist; das heißt, du musst ihn mit Anführungszeichen `''` umschliessen. + +Schließlich sollte deine `blog/views.py` Datei folgendermaßen aussehen: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Das war's! Zeit, zurück zum Template zu gehen und das QuerySet anzuzeigen! + +Wenn du mehr über QuerySets in Django erfahren willst, dann sieh unter diesem Link nach: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/de-DE/extend_your_application/README.md b/de-DE/extend_your_application/README.md new file mode 100644 index 00000000000..546a3170994 --- /dev/null +++ b/de-DE/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Erweitere deine Anwendung + +Wir haben bereits die verschiedenen Schritte für die Erstellung unserer Website abgeschlossen: Wir wissen, wie man Models, URLs, Views und Templates schreibt. Wir wissen auch, wie wir unsere Website verschönern. + +Zeit zu üben! + +Das erste, was unser Blog braucht, ist eine Seite, auf der ein einzelner Blogpost dargestellt wird, oder? + +Wir haben bereits ein `Post`-Model, deshalb brauchen wir nichts zur `models.py` hinzufügen. + +## Erstelle eine Template-Verknüpfung + +Wir beginnen damit, einen Link in der `blog/templates/blog/post_list.html`-Datei zu erstellen. Öffne sie im Code-Editor, und bisher sollte sie etwa so aussehen: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}Wir wollen einen Link vom Titel eines Posts in der Post-Liste zur Detailseite des jeweiligen Posts haben. Ändern wir `

{{ post.title }}

`, so dass es zu der Detailseite verlinkt:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Es ist an der Zeit, das mysteriöse `{% url 'post_detail' pk=post.pk %}` zu erklären. Wie du dir wahrscheinlich schon denkst, bedeutet `{% %}`, dass wir Django-Template-Tags verwenden. Dieses Mal verwenden wir eines, das eine URL für uns erzeugen wird! {% endraw %} + +Der `post_detail`-Teil bedeutet, dass Django eine URL in `blog/urls.py` mit dem Namen name=post_detail erwartet. + +Und was ist mit `pk=post.pk`? `pk` ist die Abkürzung für primary key (zu Deutsch: Primär-Schlüssel), ein eineindeutiges Identifikationsmerkmal zu jedem Eintrag in einer Datenbank. Jedes Django-Modell hat ein Feld, das als Primär-Schlüssel dient. Welchen Namen dieses Feld auch haben mag, es kann ebenfalls als "pk" referenziert werden. Da wir keinen Primär-Schlüssel in unserem `Post`-Modell angelegt haben, erstellt Django einen für uns (standardmäßig ist dies ein Feld namens "id", welches eine Zahl enthält, die mit jedem weiteren Eintrag nach oben gezählt wird, z.B. 1, 2, 3) und fügt ihn als Feld zu jedem unserer Posts hinzu. Wir greifen auf den Primär-Schlüssel zu, indem wir `post.pk` schreiben, genauso wie wir auf andere Felder (`title`, `author`, usw.) in unserem `Post`-Objekt zugreifen! + +Wenn wir jetzt http://127.0.0.1:8000/ aufrufen, erhalten wir einen Fehler (wie erwartet, da wir ja noch keine URL oder *View* für `post_detail` erstellt haben). Er wird so aussehen: + +![NoReverseMatch Error](images/no_reverse_match2.png) + +## Erstelle eine URL für die Post-Detailseite + +Lass uns eine URL in `urls.py` für unsere `post_detail`-*View* erstellen! + +Wir wollen, dass unsere erste Blogpost-Detailseite unter dieser **URL** angezeigt wird: http://127.0.0.1:8000/post/1/ + +Lass uns eine URL in der Datei `blog/urls.py` anlegen, um Django auf die *View* `post_detail` zu verweisen, welche dann den ganzen Blogpost anzeigen wird. Öffne die Datei `blog/urls.py` im Code-Editor und füge die Zeile `path('post//', views.post_detail, name='post_detail'),` hinzu, so dass die Datei wie folgt aussieht: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +Der Teil `post//` definiert ein URL-Muster – wir erklären es dir: + +- `post/` heißt, dass die URL mit dem Wort **post** beginnen sollte, gefolgt von einem **/**. So weit, so gut. +- `` – Dieser Teil ist schwieriger. Er bedeutet, dass Django eine Ganzzahl (einen Integer-Wert) erwartet und diese in Form einer Variablen namens `pk` einer View weitergibt. +- `/` – dann brauchen wir vor dem Abschluss der URL wieder einen **/**. + +Wenn du also `http://127.0.0.1:8000/post/5/` in deinen Browser eingibst, wird Django verstehen, dass du nach einer *View* suchst, die `post_detail` heißt, und wird der *View* die Information weitergeben, dass `pk` dabei `5` sein soll. + +So, jetzt haben wir der `blog/urls.py` ein neues URL-Muster hinzugefügt! Lass uns die Seite http://127.0.0.1:8000/ neu laden - Bumm! Der Server läuft wieder nicht mehr. Schau in die Konsole - wie erwartet gibt es noch einen anderen Fehler! + +![AttributeError](images/attribute_error2.png) + +Erinnerst du dich, was der nächste Schritt ist? Eine View hinzufügen! + +## Füge eine View hinzu + +Dieses Mal bekommt unsere *View* den extra Parameter `pk`. Unsere *View* muss diesen entgegennehmen, richtig? Also definieren wir unsere Funktion als `def post_detail(request, pk)`. Beachte, dass der Parameter genau den gleichen Variablennamen haben muss, wie wir in `urls` festgelegt haben (`pk`). Beachte zudem, dass das Weglassen dieser Variable unzulässig ist und zu einem Fehler führt! + +Jetzt benötigen wir also genau einen bestimmten Blogpost. Diesen finden wir, indem wir ein QuerySet folgendermaßen schreiben: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +Aber bei diesem Code gibt es ein Problem. Wenn es kein `Post`-Objekt mit diesem `primary key` (`pk`) gibt, bekommen wir einen super-hässlichen Fehler! + +![DoesNotExist Error](images/does_not_exist2.png) + +Das wollen wir nicht! Zum Glück stellt uns Django etwas zur Verfügung, das uns dieses Problem abnimmt: `get_object_or_404`. Wenn es kein `Post`-Objekt mit einem gegebenen `pk` gibt, wird eine schöne Seite angezeigt, die sogenannte `Page Not Found 404`-Seite ("Seite nicht gefunden"-Seite). + +![Page not found](images/404_2.png) + +Die gute Neuigkeit ist, dass du auch deine eigene `Page not found`-Seite erstellen und diese so hübsch gestalten kannst, wie du willst. Aber das ist jetzt gerade nicht so wichtig, deshalb überspringen wir das. + +Okay, es wird Zeit, die *View* zu unserer `views.py`-Datei hinzuzufügen! + +In `blog/urls.py` haben wir eine URL-Regel namens `post_detail` erstellt, die auf eine View namens `views.post_detail` verweist. Das heißt, dass Django eine View-Funktion erwartet, die `post_detail` heißt und in `blog/views.py` angelegt wurde. + +Wir sollten also `blog/views.py` im Code-Editor öffnen und den folgenden Code zu den anderen `from` Zeilen hinzufügen: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +Und am Ende der Datei werden wir unsere *View*-Funktion ergänzen: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Super. Lass uns nun http://127.0.0.1:8000/ neu laden. + +![Die post_list-View](images/post_list2.png) + +Es hat funktioniert! Aber was passiert, wenn du auf den Link im Blog-Titel klickst? + +![TemplateDoesNotExist Error](images/template_does_not_exist2.png) + +Oh nein! Ein anderer Fehler! Aber wir wissen ja schon, wie wir mit diesem umgehen, oder? Wir müssen ein Template hinzufügen! + +## Erstelle ein Template für die Post-Detailseite + +Wir erstellen eine Datei in `blog/templates/blog` mit dem Namen `post_detail.html` und öffnen sie im Code-Editor. + +Gib den folgenden Code ein: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +Wir erweitern wieder `base.html`. Im `content`-Block wollen wir das Publikationsdatum eines Posts (published_date), falls es existiert, anzeigen und auch den Titel und den Text. Aber wir müssen noch ein paar wichtige Dinge klären, oder? + +{% raw %}`{% if ... %} ... {% endif %}` ist ein Template-Tag, das wir benutzen können, wenn wir etwas überprüfen möchten. (Erinnerst du dich an `if ... else ...` vom Kapitel **Einführung in Python**?) In diesem Fall hier wollen wir prüfen, ob das `published_date`-Feld eines Post-Objektes nicht leer ist. {% endraw %} + +OK, aktualisieren wir unsere Seite und sehen, ob `TemplateDoesNotExist` jetzt weg ist. + +![Blogpost-Detailseite](images/post_detail2.png) + +Yay! Es funktioniert! + +# Veröffentlichen! + +Es wäre schön zu sehen, ob deine Website noch auf PythonAnywhere funktioniert, richtig? Lass sie uns erneut veröffentlichen. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "View und Template für Blogpost-Details sowie CSS für die Website hinzugefügt" + $ git push + + +Dann führe Folgendes in der [PythonAnywhere-Bash-Konsole](https://www.pythonanywhere.com/consoles/) aus: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Denk daran, `` durch deine tatsächliche PythonAnywhere-Subdomain zu ersetzen - ohne die spitzen Klammern.) + +## Die statischen Dateien auf dem Server aktualisieren + +Server wie PythonAnywhere behandeln statische Dateien ("static files", z.B. CSS-Dateien) anders als Python-Dateien, weil statische Dateien noch optimiert und dadurch dann schneller geladen werden können. Deswegen müssen wir, nachdem wir Änderungen an den CSS Dateien vorgenommen haben, einen zusätzlichen Befehl auf dem Server ausführen, um diese Dateien zu aktualisieren. Der Befehl heißt `collectstatic`. + +Aktiviere also deine virtuelle Umgebung, wenn sie nicht vom letzten Mal noch aktiv ist (PythonAnywhere benutzt dazu das Kommando `workon`, das ist ähnlich wie `source myenv/bin/activate`, das du auf deinem Computer verwendest): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +Der `manage.py collectstatic` Befehl ist ein bisschen wie `manage.py migrate`. Wir machen ein paar Änderungen in unserem Code und dann sagen wir Django, dass es diese übernehmen (*apply*) soll, entweder zu der servereigenen Sammlung von statischen Dateien oder in die Datenbank. + +Auf jeden Fall sind wir nun soweit, dass wir [auf die Seite "Web"](https://www.pythonanywhere.com/web_app_setup/) wechseln können (mittels dem Menü-Knopf in der Ecke oben rechts) und **Reload** klicken können. Schau dir dann die Seite https://subdomain.pythonanywhere.com an, um das Ergebnis zu sehen. + +Und das war's. Glückwunsch! :) \ No newline at end of file diff --git a/de-DE/how_the_internet_works/README.md b/de-DE/how_the_internet_works/README.md new file mode 100644 index 00000000000..ab728a10ce6 --- /dev/null +++ b/de-DE/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# Wie das Internet funktioniert + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) behandelt. +> +> Dieses Kapitel wurde inspiriert durch den Vortrag "How the Internet works" von Jessica McKellar (http://web.mit.edu/jesstess/www/). + +Wahrscheinlich nutzt du das Internet jeden Tag. Aber weißt du, was passiert, wenn du eine Adresse wie https://djangogirls.org im Browser eingibst und `enter` drückst? + +Als Erstes solltest du wissen, dass eine Webseite meist nur ein paar Dateien auf der Festplatte sind -- so wie deine Filme, deine Musik oder deine Bilder. Das Besondere an Webseiten ist, dass sie aus speziellem Computer-Code bestehen, das sogenannte HTML. + +Wenn du noch nie etwas mit Programmierung zu tun hattest, kann auch HTML zuerst abschreckend aussehen, aber dein Browser (Chrome, Safari, Firefox, etc.) liebt es. Browser sind so entworfen, dass sie diesen Code verstehen, seinen Anweisungen folgen können und diese Dateien, aus denen deine Website besteht, genau so darstellen, wie du es möchtest. + +Wie jede andere Datei auch, muss die HTML-Datei irgendwo auf einer Festplatte gespeichert werden. Für das Internet verwenden wir spezielle, leistungsstarke Computer, sogenannte *Server*. An ihnen sind normalerweise weder Bildschirm, Maus oder Tastatur angeschlossen, weil der Hauptzweck der Server darin besteht, Daten zu speichern und zur Verfügung zu stellen. Darum nennt man sie *Server* - sie *bedienen* (serve) dich mit Daten. + +OK, aber du willst wissen, wie das Internet aussieht oder? + +Wir haben ein Bild gemalt. So sieht es aus: + +![Abbildung 1.1](images/internet_1.png) + +Ziemliches Durcheinander, oder? Eigentlich ist es ein Netzwerk aus verbundenen Maschinen (den oben genannten *Servern*). Hunderttausende von Rechnern! Kilometer über Kilometer Kabel rund um die Welt. Auf einer Webseite über Unterseekabel (https://submarinecablemap.com/) kannst du dir ein Bild von der Komplexität des Netzes machen. Hier ist ein Screenshot der Seite: + +![Abbildung 1.2](images/internet_3.png) + +Faszinierend, oder? Es ist jedoch nicht möglich, Kabel zwischen allen Servern des Internets zu schalten. Damit wir eine Maschine (z.B. diejenige, auf welcher https://djangogirls.org abgespeichert ist) erreichen können, muss unsere Anfrage über viele verschiedene andere Maschinen weitergeleitet werden. + +Das sieht ungefähr so aus: + +![Abbildung 1.3](images/internet_2.png) + +Stell dir vor, wenn du https://djangogirls.org in den Browser eingibst, würdest du einen Brief versenden, in dem steht; "Hallo Django Girls, ich möchte die djangogirls.org Webseite ansehen. Bitte schickt sie mir!" + +Der Brief kommt ins Postamt in deiner Nähe. Von da aus gelangt er zu einem anderen Postamt näher an der Zieladresse und näher und näher, bis der Brief zugestellt werden kann. Die einzigartige Sache ist, dass, wenn du mehrere Briefe (*Datenpakete*) zu der selben Adresse abschickst, jeder einzelne Brief durch komplett unterschiedliche Poststellen (*Router*) laufen könnte. Dies hängt davon ab, wie sie an jedem Standort verteilt werden. + +![Abbildung 1.4](images/internet_4.png) + +So einfach ist das im Prinzip. Du sendest Nachrichten und erwartest eine Antwort. Anstelle von Papier und Stift verwendest du Daten, aber die Idee ist dieselbe! + +Anstelle von Adressen mit Straße, Ort und Postleitzahl verwenden wir IP-Adressen. IP steht für Internet Protocol. Dein Computer fragt erst das DNS (Domain Name System), um die (von Menschen besser lesbare) Adresse djangogirls.org in die (besser von Maschinen lesbare) IP-Adresse umzuwandeln. Das DNS ist ein bisschen wie ein altmodisches Telefonbuch aus Papier, in dem du den Namen einer Person, die Du kontaktieren willst, suchen und die Telefonnummer und Adresse nachgucken kannst. + +Wenn du einen Brief versenden willst, brauchst du spezielle Eigenschaften wie: Postanschrift, Briefmarke etc. Außerdem musst du eine Sprache verwenden, die der Empfänger versteht. Das gleiche gilt für die *Datenpakete*, die du sendest, um eine Website betrachten zu können. Wir verwenden ein Protokoll namens HTTP (Hypertext Transfer Protocol). + +Grundsätzlich brauchst du also für eine Website auch einen *Server*, auf dem sie abgelegt ist. Wenn der *Server* eine eingehende *Anforderung* (in einem Brief) empfängt, sendet er deine Website zurück (in einem weiteren Brief). + +Da dies hier ein Django-Tutorial ist, fragst du dich vielleicht, was Django in diesem Zusammenhang macht. Wenn dein Server eine Antwort zurück sendet, soll nicht an jeden dasselbe gesendet werden. Es wäre besser, wenn die Antworten individuell personalisiert würden, entsprechend der Anfragen des jeweiligen Briefes, oder? Django hilft dir, diese personalisierten und interessanten Antworten zu erstellen. :) + +Genug der Theorie, lass uns loslegen! \ No newline at end of file diff --git a/de-DE/html/README.md b/de-DE/html/README.md new file mode 100644 index 00000000000..6f6cbd62cbb --- /dev/null +++ b/de-DE/html/README.md @@ -0,0 +1,227 @@ +# Einführung in HTML + +Vielleicht fragst du dich, was ein Template (Vorlage) ist? + +Ein Template (zu deutsch "Vorlage") ist eine Textdatei und ermöglicht es uns, verschiedene Inhalte in einer einheitlichen Darstellung zu erzeugen. Eine Vorlage für z.B. einen Brief hilft uns, immer gleich aussehende Nachrichten zu versenden, in denen sich Empfänger, Betreff und Text jeweils ändern, das äußere Format jedoch bestehen bleibt. + +Ein Django-Template wird mit einer Sprache namens HTML beschrieben. (Genau das HTML aus dem ersten Kapitel: **Wie das Internet funktioniert**). + +## Was ist HTML? + +HTML ist recht einfacher Code, der von deinem Browser – z.B. Chrome, Firefox oder Safari – interpretiert wird, um dem Benutzer eine Website darzustellen. + +HTML steht für "HyperText Markup Language". Als **HyperText** wird Text bezeichnet, der über markierte Textstellen, den "Hyperlinks" (die umgangssprachlichen "Links"), auf andere (meist ebenfalls in HTML geschriebene) Seiten verweist. **Markup** bedeutet, dass wir ein Dokument nehmen und mit Code versehen, um einem Empfänger mitzuteilen (in diesem Fall dem Browser), wie diese Seite interpretiert werden muss. HTML-Code besteht aus **Tags**, wovon jeder mit `<` beginnt und mit `>` endet. Diese Tags stellen die Markup-**Elemente** dar. + +## Dein erstes Template! + +Ein Template zu erstellen, heißt, eine entsprechende Datei dafür zu erstellen. Alles ist eine Datei, wie du vielleicht schon bemerkt hast. + +Templates werden im Verzeichnis `blog/templates/blog` gespeichert. Als Erstes erzeugen wir das Verzeichnis `templates` in deinem Blog-Verzeichnis. Im Template-Verzeichnis selbst erstellen wir ein weiteres Verzeichnis `blog`: + + blog + └───templates + └───blog + + +(Falls du dich wunderst, warum wir zwei `blog`-Verzeichnisse brauchen – das hängt mit den nützlichen Namenskonventionen von Django zusammen, die das Leben einfacher machen, wenn deine Projekte immer komplizierter und komplexer werden.) + +Als nächstes erstellen wir eine Datei `post_list.html` (erst mal ohne Inhalt) innerhalb des Verzeichnisses `blog/templates/blog`. + +Kontrolliere deine überarbeitete Webseite unter: http://127.0.0.1:8000 + +> Falls du die Fehlermeldung `TemplateDoesNotExist` angezeigt bekommst, versuche den Server neu zu starten. Auf der Kommandozeile drückst du dafür Strg+C bzw. Ctrl+C (Strg-/Ctrl- und die C-Taste C zusammen) und startest danach den Server erneut mit dem Kommando `python manage.py runserver`. + +![Abbildung 11.1](images/step1.png) + +Der Fehler sollte weg sein! Gratulation! :) Deine Webseite ist allerdings noch leer, weil dein Template leer ist. Das müssen wir ändern. + +Öffne die neue Datei im Code-Editor, und füge Folgendes hinzu: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Halli-Hallo!

+

Es funktioniert!

+ + +``` + +Hat sich die Seite geändert? Besuche http://127.0.0.1:8000/, um nachzusehen. + +![Abbildung 11.2](images/step3.png) + +Es funktioniert. Gute Arbeit! :) + +* Die Zeile `` ist kein HTML-Tag. Es deklariert nur den Dokumententyp. Hier informiert sie den Browser, dass der Dokumententyp [HTML5](https://html.spec.whatwg.org/#the-doctype) ist. Jede HTML5-Datei muss so anfangen. +* Der eigentliche HTML-Teil beginnt immer mit `` und endet immer mit ``. Zwischen den beiden Tags `` und `` steht der gesamte Inhalt der Webseite +* `

` ist der Tag für ein Absatz-Element (paragraph), `

` beendet einen Absatz + +## "Head" und "body" + +Jede HTML-Seite gliedert sich in zwei Teile: **head** und **body**. + +* Das Element **head** speichert im "Kopf" der Seite Informationen über die Seite, die dir nicht angezeigt werden. + +* Das Element **body** enthält den "Körper" - also den dargestellten Inhalt der Seite. + +Im `` informieren wir den Browser über Einstellungen und Konfigurationen der Webseite, z.B. wie sie dargestellt werden soll, und im `` darüber, was tatsächlich dargestellt werden soll. + +In den `` können wir z.B. noch den Titel (title) der Seite mit aufnehmen: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Olas blog + + +

Halli-Hallo!

+

Es funktioniert!

+ + +``` + +Speichere die Datei und aktualisiere die Seite im Browser. + +![Abbildung 11.3](images/step4.png) + +Der Titel "Olas Blog" wird nun im Browser angezeigt. Hast du es bemerkt? Der Browser hat `Olas Blog` interpretiert und in die Titelleiste übernommen (dieser Titel wird auch in den Lesezeichen usw. verwendet). + +Wie du vielleicht bemerkt hast, hat jedes Element zu Beginn einen öffnenden Tag und einen zugehörigen *schließenden Tag* mit `/` und innerhalb davon sind Elemente *eingebettet*. Ein innerer Tag kann nicht außerhalb des umschließenden Tags geschlossen werden, die Reihenfolge muss immer stimmen. + +Es ist, wie wenn man Sachen in Kisten steckt. Du hast eine große Kiste, ``. In der ist als weitere, etwas kleinere Kiste `` drin, und in der wiederum weitere kleine Kistchen: `

`. + +Die Regeln und Reihenfolgen von *schließenden* Tags und *Verschachtelung* der Elemente musst du immer einhalten. Anderenfalls können Browser die Seite nicht richtig interpretieren und darstellen. + +## Dein Template anpassen + +Jetzt kannst du ein bisschen rumprobieren und dein Template umgestalten! Hier sind ein paar nützliche Tags dafür: + +* `

Überschrift

` (headline) für wichtigste Überschriften +* `

Unter-Überschrift

` die nächst tiefere Überschiftenebene +* `

Unter-Unter-Überschrift

` ... und so weiter bis `
` +* `

Ein Fliesstext-Absatz

` +* `Text` hebt deinen Text hervor +* `Text` hebt deinen Text stark hervor +* `
` fängt eine neue Zeile an (du kannst nichts in das br schreiben und es gibt keinen schließenden Tag) +* `link` erstellt einen Link +* `
  • Erster Punkt
  • second item
` generiert eine Liste so wie diese hier! +* `
` definiert einen Abschnitt auf einer Seite +* `` definiert eine Reihe von Navigationslinks +* `
` definiert voneinander unabhängige, eigenständige Inhalts-Teile +* `
` definiert einen Abschnitt in einem Dokument +* `
` gibt eine Kopfzeile für ein Dokument oder einen Abschnitt an +* `
` enthält den Hauptinhalt eines Dokuments +* `` definiert eine Nebenbemerkung (wie den Inhalt einer Rand-Leiste) zum Inhaltsteil, in dem es platziert wird +* `
` definiert eine Fußzeile für ein Dokument oder einen Abschnitt +* `` definiert eine bestimmte Zeit (oder einen Zeitpunkt samt Datum) + +Hier ist ein vollständiges Beispiel eines Templates. Kopiere es und füge es in `blog/templates/blog/post_list.html` ein: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+        
+     + +``` + +Wir haben hier einen `header`-Abschnitt und zwei `article`-Abschnitte erstellt. + +* Das `header`-Element enthält den Titel unseres Blogs – eine Überschrift und einen Link +* Die beiden `Artikel` Elemente enthalten unsere Blogeinträge mit einem veröffentlichten Datum in einem `time` Element, ein `h2` Element mit einem anklickbaren Beitragstitel und einem `p` (Absatz) Element für den Text unseres Blogeintrags. + +Wir bekommen das Folgende: + +![Abbildung 11.4](images/step6.png) + +Yaaay! Bis jetzt zeigt unser Template aber immer genau die **gleichen Inhalte** – obwohl wir aber vorhin davon gesprochen haben, dass Templates uns erlauben, **verschiedene** Informationen im **gleichen Format** darzustellen. + +Eigentlich wollen wir richtige Posts anzeigen, die in unserer Django-Admin-Oberfläche hinzugefügt wurden – und das wollen wir als Nächstes tun. + +## Noch eine Sache: Deployment! + +Es wäre gut, das alles live draußen im Internet zu sehen, oder? Lass uns noch eine PythonAnywhere-Anwendung erstellen: + +### Committe und pushe deinen Code auf GitHub + +Lass uns nachsehen, welche Dateien sich nach dem letzten Veröffentlichen (Deployment) geändert haben. (Führe diese Befehle lokal aus und nicht auf PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Stelle sicher, dass du im `Djangogirls` Verzeichnis bist und sag `git`, dass alle Änderungen in diesem Verzeichnis hinzugefügt werden sollen: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +Bevor wir alle Dateien hochladen, prüfen wir noch einmal, was `git` hochladen will (alle Dateien, die `git` hochladen wird, sind jetzt grün): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Fast fertig, wir sagen nun noch, dass diese Änderung in der Verlaufsübersicht gespeichert werden soll. Wir erstellen eine "Commit Message", die beschreibt, was wir verändert haben. Du kannst an diesem Punkt hier alles reinschreiben, aber es ist sehr nützlich, etwas Sinnvolles einzutragen, damit du dich in Zukunft erinnern kannst, was du geändert hast. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "HTML der Site geändert." + + +> **Beachte:** Du musst Anführungszeichen um den Commit-Kommentar setzen. + +Nachdem wir das gemacht haben, laden (push) wir unsere Änderungen auf GitHub: + +{% filename %}command-line{% endfilename %} + + $ git push + + +### Hol dir den neuen Code auf PythonAnywhere und aktualisiere deinen Browser + +* Öffne die [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) und gehe zu deiner **Bash-Konsole** (oder starte eine neue). Dann, führe Folgendes aus: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +Du musst `` durch deine tatsächliche PythonAnywhere-Subdomain zu ersetzen - ohne die spitzen Klammern. Normalerweise ist deine Subdomain dein PythonAnywhere-Benutzername, aber in manchen Fällen ist sie leicht anders (z.B. wenn dein Benutzername Großbuchstaben enthält). Wenn dieser Befehl also nicht funktioniert, verwende den Befehl `ls` (listet Dateien auf), um den tatsächlichen Subdomain-/Ordner-Name herauszufinden, und verwende dann `cd`, um dorthin zu wechseln. + +Nun sieh zu, wie dein Code heruntergeladen wird. Wenn du überprüfen willst, dass er angekommen ist, geh' hinüber zur **Seite "Files"** and schau deinen Code auf PythonAnywhere an (du kannst andere PythonAnywhere-Seiten über den Menü-Knopf auf der Konsolen-Seite erreichen). + +* Spring anschließend rüber zur [Seite "Web"](https://www.pythonanywhere.com/web_app_setup/) und klick auf **Neu laden** in deinem Browser. + +Dein Update sollte live sein! Lade die Seite neu in deinem Browser. Es sollten nun Änderungen zu sehen sein. :) \ No newline at end of file diff --git a/de-DE/installation/README.md b/de-DE/installation/README.md new file mode 100644 index 00000000000..ed709da2433 --- /dev/null +++ b/de-DE/installation/README.md @@ -0,0 +1,68 @@ +# Wenn du dieses Tutorial zu Hause bearbeitest + +Wenn du das Tutorial zu Hause bearbeitest, und nicht auf einer der [Django Girls Veranstaltungen](https://djangogirls.org/events/), kannst du dieses Kapitel komplett überspringen und direkt mit dem Kapitel [Wie funktioniert das Internet?](../how_the_internet_works/README.md) fortfahren. + +Dem ist so, weil wir die Dinge jeweils installieren werden, wenn sie im Tutorial benötigt werden. Das hier ist nur eine zusätzliche Seite, die alle Installationsanleitungen an einem Ort bündelt (was für manche Veranstaltungsformate nützlich ist). Falls du willst, kannst du alles auf dieser Seite bereits jetzt installieren. Wenn du jedoch mit dem Lernen beginnen willst, bevor du eine Hand voll Sachen auf deinem Computer installierst, überspringe dieses Kapitel und lies unsere Erklärungen zur Installation später im Tutorial. + +Viel Erfolg! + +# Wenn du an einem Workshop teilnimmst + +Wenn du an einer [Django Girls Veranstaltung](https://djangogirls.org/events/) teilnimmst: + +* Vielleicht hat deine Veranstaltung eine "Installationsparty" vor dem eigentlichen Workshoptag. Wenn du gerade auf einer Installationsparty bist, ist das deine Seite! Folge den Anweisungen hier, um alles Notwendige für den Workshop zu installieren. Frage deinen Coach, wenn du Hilfe brauchst. Am Workshoptag kannst du dann die Installationsanweisungen überspringen, auf die du im Tutorial stößt. +* Vielleicht haben die Organisatoren des Workshops dich gebeten, zu versuchen, schon zu Hause möglichst alles Benötigte auf deinem Computer zu installieren. Wenn du dazu aufgefordert wurdest, dann bist du hier auf der richtigen Seite! Folge den Anweisungen hier so gut, wie du kannst. Wenn du am Workshoptag dann im Tutorial auf einen Installationsschritt triffst, der dir zu Hause nicht gelungen ist, frage deinen Coach um Hilfe. +* Wenn dein Workshop keine Installationsparty hat (oder du nicht teilnehmen konntest) und die Organisatorien dich nicht gebeten haben, alles zu Hause zu installieren, dann überspring die Seite und geh direkt zum Kapitel [Wie das Internet funktioniert](../how_the_internet_works/README.md). Denn du wirst dann alles installieren, während du das Tutorial durcharbeitest. + +# Installation + +In diesem Tutorial wirst du einen Blog bauen. Dafür wirst du während des Tutorials aufgefordert, verschiedene Software auf deinem Computer zu installieren und auch einige Online-Konten anzulegen, wenn sie gebraucht werden. Diese Seite fasst alle Installations- und Kontoeinrichtungs-Anweisungen an einer Stelle zusammen (das ist für einige Workshopformate sinnvoll). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Kurze Einführung in die Kommandozeile {#command-line} + +Viele der folgenden Schritte beziehen sich auf die "Konsole", das "Terminal", das "Kommandozeilen-Fenster" oder die "Kommandozeile" -- all diese Begriffe bezeichnen dasselbe: Ein Fenster auf deinem Computer, in das du Kommandos eingeben kannst. Im Hauptteil des Tutorials wirst du mehr über die Kommandozeile lernen. Vorerst musst du nur wissen, wie du ein Kommandozeilenfester öffnen kannst und wie eines aussieht: {% include "/intro_to_command_line/open_instructions.md" %} + +# Python installieren {#python} + +{% include "/python_installation/instructions.md" %} + +# Einen Code-Editor installieren {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Virtualenv einrichten und Django installieren {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Git installieren {#git} + +{% include "/deploy/install_git.md" %} + +# Einen GitHub-Account erstellen {#github-account} + +Gehe zu [GitHub.com](https://www.github.com) und registriere dich für ein neues, kostenfreies Benutzerkonto. Achte darauf, dass du dein Passwort nicht vergisst (füge es deinem Passwortmanager hinzu, wenn du einen benutzt). + +# Einen PythonAnywhere-Account erstellen {#pythonanywhere-account} + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Fang an zu lesen! + +Herzlichen Glückwunsch, du hast alles eingerichtet und bist nun bereit loszulegen! Wenn du vor dem Workshop noch etwas Zeit hast, wäre es hilfreich, einige der einführenden Kapitel zu lesen: + +* [Wie das Internet funktioniert](../how_the_internet_works/README.md) + +* [Einführung in die Kommandozeile](../intro_to_command_line/README.md) + +* [Einführung in Python](../python_introduction/README.md) + +* [Django - Was ist das?](../django/README.md) + +# Viel Spaß beim Workshop! + +Wenn du mit dem Workshop anfängst, kannst du direkt zum Kapitel [Dein erstes Django-Projekt!](../django_start_project/README.md) gehen, weil du den Inhalt der vorhergehenden Kapitel schon bearbeitet hast. \ No newline at end of file diff --git a/de-DE/intro_to_command_line/README.md b/de-DE/intro_to_command_line/README.md new file mode 100644 index 00000000000..08b504e69bc --- /dev/null +++ b/de-DE/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Einführung in die Kommandozeile + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Your new friend: Command Line](https://www.youtube.com/watch?v=jvZLWhkzX-8) behandelt. + +Aufregend, oder?! In ein paar Minuten wirst du deine erste Zeile Code schreiben! :) + +**Erstmal stellen wir dir deine neue Freundin vor: Die Konsole!** + +Im Folgenden zeigen wir dir, wie du das schwarze Fenster benutzt, das alle Hackerinnen nutzen. Es sieht vielleicht erstmal etwas unheimlich aus, aber es ist nur ein Programm, das darauf wartet, Anweisungen von dir zu bekommen. + +> **Hinweis:** Bitte beachte, dass wir in dem gesamten Buch die Begriffe "Verzeichnis" und "Ordner" abwechselnd gebrauchen, aber sie stehen für ein und dasselbe. + +## Was ist die Konsole? + +Das Fenster, welches gewöhnlich die **Kommandokonsole** (command line) oder **Kommandozeilen-Interface** (command-line interface) genannt wird, ist eine textbasierte Applikation zum Betrachten, Bearbeiten und Manipulieren von Dateien auf deinem Computer. Es ist dem Windows Explorer oder Finder auf dem Mac ähnlich, aber ohne die grafische Benutzeroberfläche. Andere Bezeichnungen dafür sind: *CMD*, *CLI*, *Prompt (Eingabeaufforderung)*, *Konsole* oder *Terminal*. + +## Öffnen der Konsole + +Um mit unserem Tutorial zu starten, musst du als Erstes das Kommandozeilenprogramm starten. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## Eingabeaufforderung (Prompt) + +Du solltest nun ein weißes oder schwarzes Fenster sehen, das auf deine Anweisungen wartet. + + + +Auf einem Mac- oder Linux-Rechner siehst du wahrscheinlich ein `$`, also so: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +Auf einem Windows-Rechner siehst du wahrscheinlich ein `>`, so hier: + +{% filename %}command-line{% endfilename %} + + > + + +Schau 'mal in den Linux-Abschnitt hier obendrüber -- so etwas wirst du wieder im Abschnitt PythonAnywhere später im Tutorial antreffen. + + + +Vor jedem Kommando wird das Zeichen `$` oder `>` und ein Leerzeichen vorangestellt, aber du musst das nicht hinschreiben. Dein Computer macht das für dich. :) + +> Ein kleiner Hinweis: Falls du etwas in der Art wie `C:\Users\ola>` oder `Olas-MacBook-Air:~ ola$` sehen solltest, ist das auch 100%ig korrekt. + +Der Teil bis und einschließlich `$` oder `>` heißt *Kommandozeilen-Eingabeaufforderung* oder kurz *Eingabeaufforderung*. Sie fordert dich auf, hier etwas einzugeben. + +Wenn wir im Tutorial wollen, dass du einen Befehl eingibst, schreiben wir `$` oder `>` mit hin, gelegentlich auch noch die anderen Angaben links davon. Ignoriere den linken Teil und gib nur das Kommando ein, welches rechts der Eingabeaufforderung steht. + +## Dein erstes Kommando (YAY!) + +Lass uns mit diesem Kommando beginnen: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +Und dann bestätige mit `Enter`. Das ist unser Ergebnis: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +Wie du sehen kannst, hat der Computer gerade deinen Benutzernamen ausgegeben. Toll, was? :) + +> Versuch, jeden Befehl abzuschreiben und nicht zu kopieren und einzufügen. Auf diese Weise wirst du dir mehr merken! + +## Grundlagen + +Jedes Betriebssystem hat einen geringfügig anderen Bestand an Befehlen für die Kommandozeile, beachte daher die Anweisungen für dein Betriebssystem. Lass uns das ausprobieren. + +### Aktuelles Verzeichnis + +Es wäre schön zu sehen, wo wir uns befinden, oder? Lass uns nachsehen. Gib diesen Befehl in die Konsole ein und bestätige ihn mit `Enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Hinweis: 'pwd' steht für 'print working directory' (zeige derzeitiges Arbeitsverzeichnis). + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Hinweis: "cd" steht für "change directory". Mit PowerShell kannst du auch 'pwd' verwenden, wie auf Linux oder Mac OS X. + + + +Du wirst wahrscheinlich etwas Ähnliches auf deinem Gerät sehen. Wenn du die Konsole öffnest, befindest du dich normalerweise im Heimverzeichnis deines Benutzers. + +* * * + +### Mehr über ein Kommando lernen + +Viele Befehle, die du in der Kommandozeile nutzen kannst, haben eine eingebaute Hilfe, die du anzeigen und lesen kannst! Zum Beispiel kannst du etwas über den eben verwendeten Befehl lernen: + + + +OS X und Linux haben einen `man`-Befehl, mit dem du die Hilfe über die Kommandos aufrufen kannst. Gib `man pwd` ein und schau, was angezeigt wird oder setzte `man` vor andere Kommandos und sieh dir deren Hilfe an. Das Ergebnis von `man` wird in der Regel seitenweise ausgegeben. Du kannst die Leertaste benutzen, um auf die nächste Seite zu gelangen und `q` (für engl. "quit", was "verlassen"/"rausgehen" heisst), um die Hilfeseiten zu schließen. + + + + + +Wenn du Windows benutzt, dann wird dir der Suffix `/?` für die meisten Kommandos die Hilfeseite ausgeben. Gegebenenfalls musst du nach oben scrollen, um alles zu sehen. Versuch es mal mit `cd /?`. + + + +### Anzeigen von Dateien und Unterordnern + +Nun, was befindet sich in deinem Verzeichnis? Es wäre toll, das herauszufinden. Lass uns mal schauen: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Anwendungen + Desktop + Downloads + Musik + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Hinweis: PowerShell kannst du auch 'ls' verwenden, wie auf Linux oder Mac OS X. + +* * * + +### Wechseln des Verzeichnisses + +Lass uns jetzt zu unserem Desktop-Verzeichnis wechseln: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Wenn dein Linux-Benutzerkonto auf Deutsch eingestellt ist, kann es sein, dass auch der Name des Desktop-Verzeichnisses übersetzt ist. Wenn dem so ist, musst du im obigen Befehl `Desktop` durch den übersetzten Verzeichnisnamen `Schreibtisch` ersetzen. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Schau, ob das Wechseln des Verzeichnisses funktioniert hat: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Passt! + +> Profi-Tipp: Wenn du `cd D` tippst und dann `tab` auf deiner Tastatur drückst, wird die Kommandozeile automatisch den Rest des Namens vervollständigen, wodurch du schneller navigieren kannst. Wenn es mehr als einen Ordner gibt, dessen Name mit "D" beginnt, drücke die `tab`-Taste zweimal, um eine Liste der Möglichkeiten anzuzeigen. + +* * * + +### Erstellen eines Verzeichnisses + +Wie wär's damit, ein Übungsverzeichnis auf deinem Desktop zu erstellen? So kannst du das tun: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% filename %}command-line{% endfilename %} + + > mkdir practice + + + + +Dieser kleine Befehl erstellt einen Ordner mit dem Namen `practice` auf deinem Desktop. Du kannst nun überprüfen, ob er wirklich dort ist, indem du auf deinem Desktop nachschaust oder indem du den Befehl `ls` oder `dir` ausführst! Versuch es. :) + +> Profi-Tipp: Wenn du die selben Befehle nicht immer wieder und wieder schreiben willst, verwende die `Pfeil aufwärts`- und `Pfeil abwärts`-Tasten deiner Tastatur, um durch die zuletzt verwendeten Befehle zu blättern. + +* * * + +### Übung! + +Eine kleine Herausforderung für dich: Erstelle in deinem neu erstellten `practice`-Ordner ein Verzeichnis namens `test`. (Verwende dazu die Kommandos `cd` und `mkdir`.) + +#### Lösung: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Glückwunsch! :) + +* * * + +### Aufräumen + +Wir wollen kein Chaos hinterlassen, also lass uns das bislang Geschaffene wieder löschen. + +Zuerst müssen wir zurück zum Desktop wechseln: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% filename %}command-line{% endfilename %} + + > cd .. + + + + +Durch Verwendung von `..` mit dem `cd`-Kommando wechselst du von deinem aktuellen Verzeichnis zum übergeordneten Verzeichnis (dies ist das Verzeichnis, das das aktuelle Verzeichnis enthält). + +Schau nach, wo du gerade bist: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Jetzt ist es an der Zeit, dein `practice`-Verzeichnis zu löschen: + +> **Achtung**: Wenn du Daten mit `del`, `rmdir` oder `rm` löschst, kannst du das nicht mehr rückgängig machen, das bedeutet, *die gelöschten Dateien sind für immer weg*! Sei also sehr vorsichtig mit diesem Befehl. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Geschafft! Lass uns schauen, ob es wirklich gelöscht ist: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### Beenden + +Das wärs fürs Erste. Du kannst nun beruhigt deine Konsole schließen. Lass es uns wie die Hacker machen, okay? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, was? :) + +## Zusammenfassung + +Hier ist eine Zusammenfassung einiger nützlicher Kommandos: + +| Befehl (Windows) | Befehl (Mac OS / Linux) | Beschreibung | Beispiel | +| ---------------- | ----------------------- | ------------------------------- | ---------------------------------------------------- | +| exit | exit | Fenster schließen | **exit** | +| cd | cd | Verzeichnis wechseln | **cd test** | +| cd | pwd | aktuelles Verzeichnis anzeigen | **cd** (Windows) oder **pwd** (Mac OS / Linux) | +| dir | ls | Unterordner/Dateien zeigen | **dir** | +| copy | cp | Datei kopieren | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | Datei verschieben | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | neues Verzeichnis erstellen | **mkdir testdirectory** | +| rmdir (oder del) | rm | Datei löschen | **del c:\test\test.txt** | +| rmdir /S | rm -r | Verzeichnis löschen | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | Hilfe für ein Kommando aufrufen | **cd /?** (Windows) oder **man cd** (Mac OS / Linux) | + +Das sind nur sehr wenige der Befehle, welche du in deiner Konsole verwenden kannst, aber du wirst heute nicht mehr brauchen. + +Falls du neugierig bist, findest du auf [ss64.com](http://ss64.com) eine vollständige Übersicht über alle Kommandozeilen-Befehle für alle Betriebssysteme. + +## Fertig? + +Lass uns mit Python anfangen! \ No newline at end of file diff --git a/de-DE/intro_to_command_line/open_instructions.md b/de-DE/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..26e86572959 --- /dev/null +++ b/de-DE/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Abhängig von deiner Windows-Version und deiner Tastatur sollte eine der folgenden Methoden ein Kommandozeilen-Fenster öffnen (du musst vielleicht etwas herumexperimentieren, aber du musst nicht jeden dieser Vorschläge ausprobieren): + +- Gehe zum Start-Menü oder Start-Bildschirm und gib "Eingabeaufforderung" in das Suchfeld ein. +- Klicke Start-Menü → Windows System → Eingabeaufforderung. +- Geh ins Start Menü → Alle Programme → Zubehör → Eingabeaufforderung. +- Gehe zum Startbildschirm, bewege deinen Mauszeiger zur unteren linken Bildschirmecke und klicke auf den nach unten zeigenden Pfeil, der erschienen ist (auf einem Touch-Screen streichst du mit dem Finger vom unteren Bildschirmrand nach oben). Die Apps-Seite sollte sich öffnen. Klicke auf Eingabeaufforderung im Abschnitt Windows System. +- Drücke die Windows-Taste und gleichzeitig "x" auf deiner Tastatur. Wähle "Eingabeaufforderung" aus dem Menü aus. +- Drücke die Windows-Taste und gleichzeitig "r", um das "Ausführen"-Fenster zu erhalten. Tippe "cmd" in das Feld und klicke OK. + +![Tippe "cmd" in das "Ausführen"-Fenster](../python_installation/images/windows-plus-r.png) + +Später im Tutorial wirst du zwei offene Kommandozeilen-Fenster gleichzeitig brauchen. Wenn du aber schon ein Kommandozeilen-Fenster offen hast, wirst du bei manchen Windows-Versionen einfach zu diesem geschickt, wenn du mit derselben Methode versuchst, ein zweites Fenster zu öffnen. Probiere das nun aus und achte darauf, was passiert! Wenn du nur ein Kommandozeilen-Fenster bekommst, versuche eine der anderen Methoden aus der Liste oben. Mindestens eine der Methoden sollte dazu führen, dass ein neues (zweites) Kommandozeilen-Fenster geöffnet wird. + + + + + +Öffne das Launchpad → Andere → Terminal. + + + + + +Wahrscheinlich ist es unter Programme → Zubehör → Terminal, aber das ist von deinem System abhängig. Wenn es nicht da ist, kannst du versuchen, danach zu googlen. :) + + \ No newline at end of file diff --git a/de-DE/python_installation/README.md b/de-DE/python_installation/README.md new file mode 100644 index 00000000000..6ed46093a8a --- /dev/null +++ b/de-DE/python_installation/README.md @@ -0,0 +1,15 @@ +# Lass uns mit Python anfangen + +Wir sind endlich da! + +Aber lass uns zuerst erklären, was Python ist. Python ist eine sehr beliebte Programmiersprache, die du zur Erstellung von Webseiten, Spielen, wissenschaftlichen Programmen, Computergrafiken und vielem, vielem mehr verwenden kannst. + +Python entstand in den späten 1980ern mit dem Hauptziel, von Menschen lesbar zu sein (nicht nur von Computern). Darum sieht es einfacher aus als andere Programmiersprachen. Aber keine Sorge - Python ist auch sehr mächtig! + +# Python-Installation + +> **Hinweis** Wenn du ein Chromebook verwendest, überspringe bitte dieses Kapitel und folge den Anweisungen im Kapitel [Chromebook Installation](../chromebook_setup/README.md). +> +> **Hinweis:** Falls du dich bereits durch die [Installationsschritte](../installation/README.md) gearbeitet hast, gibt es keinen Grund dies erneut zu tun – du kannst direkt zum nächsten Kapitel springen! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/de-DE/python_installation/instructions.md b/de-DE/python_installation/instructions.md new file mode 100644 index 00000000000..c27dcfb7ff7 --- /dev/null +++ b/de-DE/python_installation/instructions.md @@ -0,0 +1,117 @@ +> Für Leserinnen zuhause: Dieses Kapitel wird auch im Video [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA) behandelt. +> +> Dieses Kapital basiert auf einem Tutorial der Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Django ist in Python geschrieben. Wir brauchen Python für alles in Django. Fangen wir mit der Installation an! Wir möchten, dass du Python 3 installierst. Solltest du also bereits eine ältere Version installiert haben, musst du diese aktualisieren. Wenn du schon Version {{ book.py_min_version }} oder höher hast, ist das in Ordnung. + +Bitte installiere ein gewöhnliches Python wie folgt, selbst falls auf deinem Computer bereits Anaconda installiert ist. + + + +Bitte schau zuerst auf der "Systemtyp"-Zeile der Systeminformationsseite nach, ob auf deinem Computer eine 32-Bit-Version oder eine 64-Bit-Version von Windows läuft. Um diese Seite zu finden, versuche eine der folgenden Methoden: + +* Drücke die Windows-Taste und die Pause/Break-Taste zur selben Zeit +* Öffne dein Control Panel über das Windows Menü und navigiere dann zu System & Sicherheit, dann System +* Drücke die Windows-Taste und navigiere dann zu Einstellungen > System > Über +* Suche im Windows-Startmenü nach "Systeminformationen". Klicke dazu auf Start oder drücke die Windows-Taste, dann beginne `Systeminformationen` zu tippen. Sobald du etwas eingegeben hast, bekommst du passende Vorschläge. Wähle den Eintrag "Systeminformationen" an, sobald er erscheint. + +Du kannst Python für Windows von der Webseite https://www.python.org/downloads/windows/ herunterladen. Klicke auf den "Latest Python 3 Release - Python x.x.x" Link. Wenn du eine **64-bit**-Version von Windows benutzt, lade die Datei **Windows x86-64 executable installer** herunter. Andernfalls lade den **Windows x86 executable installer** herunter. Führe den Installer nach dem Download (per Doppelklick) aus und folge den Anweisungen des Installationsprogramms. + +Auf eine Sache solltest du achten: Während der Installation wird ein Setup-Fenster auftauchen. Stell sicher, dass du die Checkbox mit "Add Python {{ book.py_version }} to PATH" oder "Add Python to your environment variables" aktiviert hast und klicke dann auf "Install Now" wie hier gezeigt (es kann bei dir etwas anders aussehen, wenn du eine andere Version installierst): + +![Vergiss nicht, Python zum Pfad hinzuzufügen](../python_installation/images/python-installation-options.png) + +Wenn die Installation abgeschlossen ist, siehst du vielleicht ein Dialogfeld mit einem Link, wo du mehr über Python oder über die Version lernen kannst. Schließe es oder brich den Dialog ab -- du wirst darüber mehr in diesem Tutorial lernen! + +Hinweis: Falls du eine ältere Version von Windows verwendest (7, Vista oder älter) und die Installation von Python {{ book.py_version }} mit einer Fehlermeldung fehlschlägt, dann installiere alle Windows-Updates und versuche erneut, Python zu installieren. Falls der Fehler dann immer noch auftritt, installiere Python-Version {{ book.py_min_release }} von [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} benötigt Python {{ book.py_min_version }} oder höher, das weder Windows XP noch frühere Windows-Versionen unterstützt. + + + + + +> **Hinweis** Bevor du Python auf Mac OS X installierst, musst du sicherstellen, dass deine Mac-Einstellungen es erlauben, Pakete zu installieren, die nicht aus dem App Store stammen. Geh auf Systemeinstellungen (im Ordner "Programme"), klicke auf "Sicherheit", und dann auf die Registerkarte "Allgemein". Wenn "Apps-Download erlauben von:" auf "Mac App Store" gestellt ist, ändere die Einstellung auf "Mac App Store und verifizierte Entwickler". + +Auf der Website https://www.python.org/downloads/mac-osx/ findest du aktuellen Python-Installer: + +* Lade die Datei *Mac OS X 64-bit/32-bit installer* herunter, +* Doppelklicke auf *python-{{ book.py_release }}-macosx10.9.pkg*, um die Installation zu starten. + + + + + +Es ist ziemlich wahrscheinlich, dass du Python schon automatisch installiert hast. Um herauszufinden, ob das so ist (und wenn ja, welche Version du hast), öffne eine Konsole und gib das folgende Kommando ein: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +Wenn du eine andere Version von Python installiert hast, die {{ book.py_min_version }} oder höher ist, z.B. {{ book.py_min_release }}, dann musst du die Version nicht aktualisieren. Wenn du Python noch nicht installiert hast oder wenn du eine andere Python-Version willst, prüfe zuerst mit folgendem Befehl, welche Linux-Distribution du benutzt: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Folge danach je nach Ergebnis einer der unterhalb dieses Abschnitts folgenden Installationsanweisungen. + + + + + +Gib diesen Befehl in die Konsole ein: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Gib diesen Befehl in die Konsole ein: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +Auf älteren Fedora-Versionen kann es sein, dass du eine Fehlermeldung bekommst, dass das Kommando `dnf` nicht gefunden wird. Falls das passiert, musst du stattdessen `yum` verwenden. + + + + + +Gib diesen Befehl in die Konsole ein: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Prüfe, ob die Installation erfolgreich war, indem du ein Kommandozeilenfenster öffnest und den `python3`-Befehl ausführst: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +Die angezeigte Version kann bei dir eine andere sein als {{ book.py_release }} -- sie sollte aber der entsprechen, die du installiert hast. + +**Hinweis:** Wenn du unter Windows eine Fehlermeldung bekommst, dass `python3` nicht gefunden wurde, versuche es mit `python` (ohne die `3`) und prüfe, ob es dennoch eine Version von Python {{ book.py_min_version }} oder höher ist. Wenn auch das nicht funktioniert, kannst du ein neues Kommandozeilenfenster öffnen und es dort erneut versuchen; dies geschieht, wenn du ein Kommandozeilenfenster verwendet, das schon vor der Python-Installation geöffnet war. + +* * * + +Wenn es Unklarheiten gibt oder wenn etwas schief ging und du nicht weiter weißt, frage bitte deinen Coach! Manchmal laufen die Dinge einfach nicht so glatt und dann ist es besser, jemanden mit mehr Erfahrung um Hilfe zu bitten. \ No newline at end of file diff --git a/de-DE/python_introduction/README.md b/de-DE/python_introduction/README.md new file mode 100644 index 00000000000..45fae0bbc8d --- /dev/null +++ b/de-DE/python_introduction/README.md @@ -0,0 +1,1071 @@ +{% set warning_icon = '' %} + +# Einführung in Python + +> Ein Teil dieses Kapitels basiert auf dem Tutorial der Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Fangen wir an, schreiben wir Code! + +## Der Python-Prompt + +> Für Leserinnen, die sich bereits mit Python auskennen: Dieser Teil befindet sich im [Python Basics: Integers, Strings, Lists, Variables and Errors](https://www.youtube.com/watch?v=MO63L4s-20U) Video. + +Um Python zu starten, musst du an die *Kommandozeile* deines Computers. Wie das geht, weißt du bereits - denn du hast es im Kapitel [Einführung in die Kommandozeile](../intro_to_command_line/README.md) gelernt. + +Also öffne die Konsole, dann fangen wir an. + +Wir wollen eine Python Konsole öffnen, also tippe unter Windows `python` oder im Mac OS/Linux Terminal `python3` und drücke `Enter`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Dein erster Python-Befehl! + +Nach Eingabe von python3 in der Konsole ändert sich das Prompt-Zeichen zu `>>>`. Für uns bedeutet das, dass wir ab nun nur noch Python-Code eingeben können. Den Python-Prompt `>>>` musst du nicht jedesmal eingeben - dies macht Python für dich. + +Wenn du die Python-Konsole wieder verlassen möchtest, gib `exit()` ein oder nutze das Tastatur-Kürzel `Strg + Z` unter Windows bzw. `Strg + D`, wenn du einen Mac hast oder Linux verwendest. Dann bist du wieder in der normalen Konsole und der Python-Prompt `>>>` ist weg. + +Fürs Erste bleiben wir in der Python Konsole, wir wollen mehr darüber lernen. Lass uns mit ein wenig Mathematik anfangen, gib `2 + 3` ein und drück `enter`. + +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +Cool! Schon ist das Ergebnis da. Python kann rechnen! Probier einfach einige andere Befehle aus, wie z.B.: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +Um Potenzen zu berechnen, sagen wir 2 hoch 3, müssen wir Folgendes eingeben: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +Spiel ein wenig herum, dann machen wir weiter. :) + +Wie du siehst, kann Python richtig toll rechnen. Aber Python kann noch viel mehr ... + +## Strings + +Strings sind Zeichenketten. Das ist eine Folge von Buchstaben, die von Anführungszeichen umgeben sind. Gib einfach mal deinen Namen ein (bei mir "Ola"): + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" +'Ola' +``` + +Nun hast du deinen ersten String erzeugt! Dies ist eine Folge von Zeichen (also nicht nur Buchstaben, wie ich oben schrieb, sondern Zeichen aller Art), die von einem Computer verarbeitet werden können. Ein String muss stets mit dem gleichen Zeichen beginnen und enden. Dies kann entweder ein einzelnes Gänsefüßchen sein (`'`) oder ein doppeltes (`"`), da gibt es keinen Unterschied! Die Anführungszeichen zeigen Python nur an, dass alles dazwischen ein String ist. + +Strings können zusammengesetzt werden. Versuch es einmal: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +Du kannst Strings auch vervielfältigen: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +Brauchst du einen Apostroph in einem String, so hast du zwei Möglichkeiten. + +Du kannst für den String doppelte Anführungszeichen verwenden: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +oder du kannst den Apostroph mit einem Backslash (``) markieren: + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Toll, was? Um deinen Namen in Großbuchstaben anzuzeigen, gib Folgendes ein: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +Hier hast du die `upper`-**Methode** auf den String angewendet! Eine Methode (wie `upper()`) ist eine Abfolge von Anweisungen, die Python für ein gegebenes Objekt (hier `"Ola"`) ausführt, wenn sie aufgerufen wird. + +Nehmen wir an, du möchtest die Zahl der Buchstaben in deinem Namen wissen. Auch dafür gibt es eine **Funktion**! + +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +Nun fragst du dich sicher, warum du manchmal eine Methode mit einem `.` am Ende des Strings (wie bei `"Ola".upper()`) schreibst und manchmal eine Funktion direkt aufrufst und den String dahinter in Klammern setzt? Im ersten Fall gehören solche Methoden, wie `upper()`, zu Objekten (hier: ein String) und funktionieren auch nur bei diesen. In solchen Fällen bezeichnen wir eine Funktion als **Methode**. Andere Funktionen sind dagegen allgemeiner und können auf unterschiedliche Datentypen angewendet werden, wie beispielsweise `len()`. Daher übergeben wir `"Ola"` als Parameter an die `len` Funktion. + +### Zusammenfassung + +Ok, genug über Strings. Bisher haben wir Folgendes kennengelernt: + +- **Der Prompt** - Wenn wir beim Python-Prompt Anweisungen (oder Programm-Code) in Python eingeben, dann erhalten wir auch Ergebnisse in Python. Man sagt zu dieser Python-Umgebung auch "Python-Shell". +- **Zahlen und Strings** - In Python nutzen wir Zahlen für Berechnungen und Strings für Text-Objekte. +- **Operatoren**, wie + und *, verarbeiten mehrere Werte und erzeugen als Ergebnis einen neuen Wert. +- **Funktionen** - wie upper() und len(), tun etwas mit Objekten (in unserem Beispiel ändern sie diese, wie bei upper(), oder sie geben eine Eigenschaft zurück, wie bei len()). + +Das sind Grundlagen jeder Programmiersprache, die Du lernen wirst. Bist Du bereit für mehr? Bestimmt! + +## Fehler + +Probieren wir etwas Neues: Errors. Können wir die Länge einer Zahl auf die gleiche Weise ermitteln, wie die Länge eines Namens? Gib dazu `len(304023)` ein und drücke auf Enter: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +Wir haben unsere erste Fehlermeldung (Error) erhalten! Mit dem Icon {{ warning_icon }} teilen wir dir in diesem Tutorial jeweils mit, dass der einzugebende Code nicht wie erwartet funktionieren wird. Fehler zu machen (selbst absichtlich) ist ein wesentlicher Teil beim Lernen! + +Unser erster Fehler sagt, dass Objekte vom Typ "int" (Integers, das sind ganze Zahlen) keine Länge haben. Was also nun? Vielleicht sollten wir unsere Zahl als String schreiben? Denn bei Strings funktioniert es ja, wie wir wissen. + +{% filename %}command-line{% endfilename %} + +```python +>>> len(str(304023)) +6 +``` + +Ja, das funktioniert! Hier haben wir die `str`-Funktion innerhalb der Funktion `len` aufgerufen. `str()` konvertiert alles zu einem String. + +- Die `str`-Funktion wandelt den übergebenen Wert in einen **String** um. +- Die `int`-Funktion wandelt den übergebenen Wert in einen **Integer** um. + +> Wichtig: Zwar können wir Zahlen in Text umwandeln, aber nicht immer auch Text in Zahlen - was beispielsweise sollte `int('hello')` ergeben? + +## Variablen + +Ein wichtiger Bestandteil beim Programmieren sind Variablen. Eine Variable ist einfach ein Name für etwas, das wir später unter genau diesem Namen wieder verwenden können. Programmiererinnen nutzen Variablen, um Daten zu speichern, den Code lesbar zu halten und um sich nicht immer alles merken zu müssen. + +Lass uns eine Variable mit der Bezeichnung `name` anlegen: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +Wir geben ein: name ist gleich "Ola". + +Du hast sicher schon bemerkt, dass Python diesmal kein Ergebnis zurückgegeben hat. Woher sollen wir nun wissen, dass es die Variable jetzt auch tatsächlich gibt? Gib `name` ein und drücke wieder auf `Enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Hurra! Deine erste Variable :)! Nun kannst du auch stets ändern, was sie enthalten soll: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +Du kannst die Variable auch in Funktionen verwenden: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Das ist toll, oder? Variablen können alles enthalten, also auch Zahlen. Versuche Folgendes: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +Was aber, wenn wir für eine Variable den falschen Namen verwenden? Uns einfach vertippen. Hast du schon eine leise Ahnung, was dann passiert? Probieren wir es aus! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +Ein Fehler! Wie du siehst, kennt Python verschiedene Arten von Fehlern. In unserem Fall hier ist es ein **NameError**. Python liefert diesen Fehler immer dann, wenn du versuchst, eine Variable zu verwenden, die es noch gar nicht gibt. Wenn du einen solchen Fehler erhältst, prüfe einfach in deinem Code, ob du dich irgendwo vertippt hast. + +Spiel einfach ein wenig rum und schaue, was alles so passiert. + +## Die print-Funktion + +Gib einmal Folgendes ein: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` + +Wenn du in der zweiten Zeile `name` eintippst, dann gibt der Python-Interpreter die String-*Darstellung* (engl. 'representation') der Variable 'name' aus. In unserem Beispiel die Buchstaben M-a-r-i-a, umschlossen von einfachen Anführungszeichen ('). Wenn du hingegen `print(name)` schreibst, dann gibt Python den Inhalt der Variablen ohne die Anführungszeichen zurück, was etwas schöner aussieht. + +Wie wir später sehen werden, ist `print()` auch recht nützlich, wenn wir etwas aus Funktionen heraus ausgeben möchten oder auch eine Ausgabe über mehrere Zeilen darstellen wollen. + +## Listen + +Außer Strings (Zeichenketten) und Integern (ganze Zahlen) hat Python noch viele andere Arten von Datentypen. Von denen wollen wir uns nun **Listen** anschauen. Listen sind genau das, was du wahrscheinlich schon vermutest: Es sind Objekte, die Listen von anderen Objekten enthalten. :) + +Legen wir los und erzeugen eine Liste: + +{% filename %}command-line{% endfilename %} + +```python +>>> [] +[] +``` + +Ja, dies ist eine leere Liste. Für uns noch nicht sehr nützlich. Legen wir nun eine Liste von Lottozahlen an. Da wir uns nicht dauernd wiederholen wollen, ordnen wir diese Liste auch direkt einer Variablen zu: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +So, nun haben wir eine Liste mit Lottozahlen! Was aber können wir damit tun? Zuerst einmal wollen wir feststellen, wie viele Zahlen in ihr enthalten sind. Hast du schon eine Idee, wie dies geht? Klar, das weißt du ja bereits! + +{% filename %}command-line{% endfilename %} + +```python +>>> len(lottery) +6 +``` + +Genau! `len()` liefert die Anzahl von Objekten in einer Liste zurück. Praktisch, nicht wahr? Nun wollen wir die Liste sortieren: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.sort() +``` + +Diese Anweisung gibt nichts zurück, sie hat aber die Reihenfolge der Objekte in der Liste geändert. Um zu sehen, was passiert ist, müssen wir die Liste ausgeben: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +Wie du siehst, sind die Zahlen in der Liste nun aufsteigend sortiert. Super! + +Aber vielleicht wollten wir es genau andersherum haben? Nichts leichter als das! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +Einfach, oder? Du kannst auch etwas zu deiner Liste hinzufügen: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +Falls du nicht immer die gesamte Liste, sondern beispielsweise nur den ersten Eintrag sehen möchtest, kannst du dafür **Indizes** benützen. Ein Index gibt die Stelle innerhalb einer Liste an, die uns interessiert. Programmierer bevorzugen es, bei 0 mit dem Zählen anzufangen. Also hat das erste Objekt in deiner Liste den Index 0, das nächste die 1 und so weiter. Gib einmal Folgendes ein: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` + +Wie du siehst, kannst du auf die einzelnen Objekte in deiner Liste zugreifen, indem du den Namen der Liste verwendest und anschließend den Index in eckigen Klammern anfügst. + +Um etwas aus deiner Liste zu löschen, musst du die **Indizes** wie gerade gelernt benutzen und die `pop()`-Methode. Lass uns ein Beispiel versuchen und das festigen, was wir zuvor gelernt haben; wir werden die erste Nummer aus unserer Liste löschen. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +Das hat doch super geklappt! + +Probier einmal andere Indizes aus: 6, 7, 1000, -1, -6 oder -1000 und versuch dir das Ergebnis vorzustellen, bevor du den jeweiligen Index verwendest. Sind die Ergebnisse sinnvoll? + +Eine Liste aller Methoden, die du auf Listen anwenden kannst, findest du in der Python-Dokumentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Installing Python Code Editor](https://www.youtube.com/watch?v=ZX1CVvZLE6c) behandelt. + +Ein Wörterbuch (von nun an mit dem englischen Begriff 'Dictionary' bezeichnet) verhält sich ähnlich wie eine Liste, jedoch greifen wir auf die enthaltenen Objekte nicht mit einem Index, sondern mit einem Schlüssel zu (auf englisch 'key', und auch hier verwenden wir im weiteren den englischen Begriff). Ein 'key' kann ein String oder eine Zahl sein. Ein leeres Dictionary legen wir wie folgt an: + +{% filename %}command-line{% endfilename %} + +```python +>>> {} +{} +``` + +Und schon hast du ein leeres Dictionary erstellt. Super! + +Nun gib einmal Folgendes ein (verwende statt 'Ola' usw. deine eigenen Informationen): + +{% filename %}command-line{% endfilename %} + +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` + +Du hast nun soeben die Variable mit dem Namen `participant` angelegt, die ein Dictionary mit drei key-value Paaren enthält (values, also Werte, sind die Objekte in einem Dictionary, - aber auch hier bleiben wir beim englischen Begriff): + +- Der key `name` verweist auf den value `'Ola'` (welches ein `string` Objekt ist), +- `country` verweist auf `'Poland'` (ebenfalls ein `string` Objekt), +- und `favorite_numbers` schließlich verweist auf `[7, 42, 92]` (eine `Liste` mit drei Zahlen). + +Auf die einzelnen Objekte in einem Dictionary kannst du wie folgt zugreifen: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(participant['name']) +Ola +``` + +Also ganz ähnlich wie bei einer Liste. Aber statt dir einen Index merken zu müssen, benutzt du bei einem Dictionary einfach einen key (hier: den String 'name'). + +Was aber geschieht, wenn wir Python nach dem Wert eines keys fragen, den es gar nicht gibt? Errätst du es schon? Probieren wir es einfach aus und schauen was passiert! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` + +Ah, wieder ein Fehler! Diesmal ein **KeyError**. Python hilft uns auch hier und sagt uns, dass es den key `'age'` in diesem Dictionary gar nicht gibt. + +Wenn du zwischen Dictionaries und Listen wählen kannst, wann sollte welche Datenstruktur verwendet werden? Das ist eine gute Frage, über die es sich nachzudenken lohnt; und vielleicht möchtest du dies kurz tun, bevor du weiterliest. + +- Du brauchst nur eine geordnete Folge von Elementen? Dann wähle eine Liste. +- Du brauchst eine Sammlung von Elementen, auf die du später einzeln, gezielt und effizient mit Hilfe eines Namens (d.h. keys) zugreifen kannst? Dann wähle ein Dictionary. + +Dictionaries sind, so wie auch Listen, *mutable*, d. h. nachträglich veränderbar. So kannst du bei Dictionaries später noch weitere key-value Paare hinzufügen: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Wie bei Listen können wir auch bei Dictionaries die `len()`-Funktion verwenden, um die Zahl der enthaltenen Einträge (das sind die key-value Paare) zu ermitteln. Probier es gleich aus und tippe dieses Kommando ein: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +Wir hoffen, dass das Alles für dich bisher Sinn ergibt. :) Bist du bereit für mehr Spaß mit Dictionaries? Machen wir weiter. + +Zum Löschen von Elementen kannst du den `pop()`-Befehl verwenden. Nehmen wir an, du möchtest den Eintrag mit dem key `'favorite_numbers'` entfernen, dann tippe: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Wie du an der Ausgabe erkennst, ist nun das key-value Paar von 'favorite_numbers' gelöscht. + +Ebenso kannst du auch den Wert eines bestehenden Eintrages ändern: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Wie du siehst, hast du nun im key-value Paar mit dem key `'country'` den Wert von `'Poland'` nach `'Germany'` geändert. :) Hurra! Schon wieder was gelernt. + +### Zusammenfassung + +Großartig! Inzwischen hast du schon einiges über Programmierung gelernt und die folgenden Dinge sind dir vertraut: + +- **Errors** - Du weißt, wie sie zu lesen sind und dass Python sie dann ausgibt, wenn es eine Anweisung von dir nicht ausführen kann. +- **Variablen** - sind Namen für Objekte, die dir dabei helfen, deinen Code leichter zu schreiben und ihn dabei auch gut lesbar zu halten. +- **Listen** - können Objekte in einer geordneten Reihenfolge speichern. +- **Dictionaries** - speichern Objekte als key-value Paare. + +Schon gespannt auf den nächsten Teil? :) + +## Vergleichen + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) behandelt. + +Ein großer Teil beim Programmieren besteht darin, Dinge zu vergleichen. Was lässt sich am besten vergleichen? Zahlen! Schauen wir uns mal an, wie das funktioniert: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +Hier haben wir Python einige Zahlen zum Vergleichen gegeben. Wie du siehst, kann Python nicht nur die Zahlen vergleichen, sondern auch die Ergebnisse von mathematischen Ausdrücken wie `2 * 2` und Funktionswerte wie die `2`, die von `len([4, 5])` zurückgegeben wird. Cool, nicht wahr? + +Womöglich wunderst du dich aber über die beiden `==` Gleichheitszeichen zum Vergleich, ob zwei Zahlen den selben Wert haben? Ein einfaches Gleichheitszeichen `=` verwenden wir bereits, um Variablen bestimmte Werte zuzuweisen. Da beim Programmieren alle Anweisungen eindeutig sein müssen, benötigst du in Python daher **stets** zwei `==` Zeichen, um Dinge auf Gleichheit zu testen. Wir können auch feststellen, ob Werte unterschiedlich sind. Dafür verwenden wir das Symbol `!=`, wie im obigen Beispiel. + +Nun noch zwei weitere Vergleiche: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +`>` und `<` sind klar, was aber sollen `>=` und `<=` bedeuten? Vergleiche liest du folgendermaßen: + +- x `>` y bedeutet: x ist größer als y +- x `<` y bedeutet: x ist kleiner als y +- x `<=` y bedeutet: x ist kleiner oder gleich y +- x `>=` y bedeutet: x ist größer oder gleich y + +Sensationell! Lust auf mehr? Dann probier das: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 3 > 2 or 2 < 1 +True +``` + +Du kannst Python beliebig viele Vergleiche vornehmen lassen und wirst ein Ergebnis erhalten. Das ist wirklich cool, oder? + +- **and** - wenn Du den `and`-Operator verwendest, müssen beide Vergleiche True (d.h. wahr) ergeben, damit das Gesamtergebnis auch True ist +- **or** - wenn Du den `or`-Operator verwendest, genügt es, wenn einer der beiden Vergleiche True ergibt, damit das Gesamtergebnis True ergibt + +Die Redewendung "Äpfel mit Birnen zu vergleichen" hast du bestimmt schon einmal gehört. Machen wir dies doch einmal in Python: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and 'str' +``` + +Unterschiedliche Dinge, hier die Datentypen Zahlen (`int`) und Strings (`str`), lassen sich auch in Python nicht miteinander vergleichen. In solch einem Fall liefert uns Python einen **TypeError** und sagt uns, dass diese zwei Datentypen nicht miteinander verglichen werden können. + +## Boolean + +Du hast gerade einen neuen Typ von Python-Objekten kennen gelernt. Er heisst **Boolean**. + +Es gibt zwei Boolean-Objekte: + +- True (wahr) +- False (falsch) + +Damit Python diese beiden Werte versteht, musst du sie auch genau so schreiben (den ersten Buchstaben groß, alle weiteren klein). **true, TRUE und tRUE funktionieren nicht – nur True ist korrekt.** (Dasselbe gilt auch für False.) + +Auch Booleans können Variablen zugewiesen werden: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +Auch Folgendes geht: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Übe ein wenig, indem du mit Booleans rumspielst, zum Beispiel mit diesen Anweisungen: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Glückwunsch! Booleans sind echt eine der coolsten Features beim Programmieren und du hast gerade gelernt, damit umzugehen! + +# Speicher es! + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk) behandelt. + +Bisher haben wir den Python-Code nur im Interpreter eingegeben, wodurch wir immer nur eine Zeile Code auf einmal ausführen konnten. Richtige Programme dagegen werden in Dateien gespeichert und, je nach Programmiersprache, durch einen **Interpreter** ausgeführt oder durch einen **Compiler** übersetzt. Unseren bisherigen Code haben wir dagegen im Python-**Interpreter** Zeile für Zeile eingegeben und einzeln ausgeführt. Für die nächsten Beispiele brauchen wir mehr als eine Zeile, daher werden wir nun: + +- Den Python-Interpreter beenden +- Einen Code-Editor unserer Wahl öffnen +- Code eingeben und diesen in einer Python-Datei sichern +- Und diesen dann laufen lassen! + +Um den Python-Interpreter zu beenden, nutze die `exit()`-Funktion + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +``` + +Nun siehst du wieder den normalen Kommandozeilen-Prompt. + +Im Kapitel [Code-Editor](../code_editor/README.md) haben wir uns bereits einen Code-Editor ausgesucht. Nun öffnen wir den Code-Editor und schreiben folgenden Code in eine neue Datei (wenn du ein Chromebook benutzt, dann erstelle eine neue Datei in der Cloud-IDE, öffne sie und du befindest dich automatisch im integrierten Code-Editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +Da du nun schon einige Python-Erfahrung hast, schreibe ein wenig Code mit dem, was du bislang gelernt hast. + +Als nächstes wollen wir diesen Code in einer Datei mit einem aussagekräftigen Namen speichern. Lass uns die Datei **python_intro.py** nennen und auf dem Desktop speichern. Wir können der Datei jeden Namen geben, den wir wollen, aber es ist wichtig sicherzustellen, dass der Dateiname auf **.py** endet. Die Erweiterung **.py** gibt unserem Betriebssystem an, dass dies ein **Python executable file** ist und Python diese ausführen kann. + +> **Hinweis:** Du wirst eines der coolsten Eigenschaften von Code-Editoren bemerken: Farben! In der Python-Konsole hatte alles die gleiche Farbe. Der Code-Editor dagegen sollte dir nun die `print`-Funktion in einer anderen Farbe anzeigen als der von ihr auszugebende Text. Dies wird "Syntax Hervorhebung" ("syntax highlighting") genannt und ist ein wirklich sehr nützliches Werkzeug beim Programmieren. Die Farbe von Dingen gibt dir Hinweise auf z.B. nicht geschlossene Zeichenfolgen oder Tippfehler in einem Schlüsselwort (wie das `def` in einer Funktion, das wir weiter unten sehen werden). Dies ist einer der Gründe, warum wir Code-Editoren verwenden. :) + +Nun, da die Datei gesichert ist, wollen wir sie ausführen! Nutze, was du bisher über die Kommandozeile (das mit dem Prompt) gelernt hast, um in der Konsole in das Desktop-Verzeichnis zu wechseln. + + + +Auf einem Mac sieht das etwa so aus: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +Unter Linux ist es ähnlich: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Denk daran, dass das "Desktop"-Verzeichnis bei dir "Schreibtisch" heißen kann.) + + + + + +In der Eingabeaufforderung von Windows wird's so sein: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +Und in der Powershell von Windows so: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +Wenn du nicht weiterkommst, frag' um Hilfe. Denn genau dafür sind die Coaches da! + +Benutze jetzt Python, um den Code in der Datei auszuführen: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hello, Django girls! + + +Hinweis: Unter Windows gibt es den 'python3'-Befehl nicht. Verwende stattdessen 'python', um die Datei auszuführen: + +{% filename %}command-line{% endfilename %} + +```python +> python python_intro.py +``` + +Prima! Du hast soeben dein erstes Python-Programm aus einer Datei heraus ausgeführt. Großartig, oder? + +Nun wollen wir uns einem wichtigen Teil der Programmierung zuwenden: + +## Wenn ... sonst-wenn ... sonst (If … elif … else) + +Oft sollen manche Programmteile nur ausgeführt werden, wenn bestimmte Vorbedingungen erfüllt sind. Dafür gibt es in Python sogenannte **if-Anweisungen**. + +Nun ändere den Code in deiner **python_intro.py** Datei: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: +``` + +Würden wir das nun speichern und anschließend ausführen, würden wir einen Fehler erhalten: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +Python erwartet hier noch weiteren Programmcode, der ausgeführt werden soll, wenn die Bedingung `3 > 2` wahr ist (also `True` ergibt). Versuchen wir, Python “It works!” ausgeben zu lassen. Ändere den Code in **python_intro.py** zu: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: + print('It works!') +``` + +Du fragst dich nun, warum wir die angefügte Zeile mit 4 Leerzeichen eingerückt haben? Damit teilen wir Python mit, dass dieser Code ausgeführt werden soll, wenn die vorhergehende Bedingung True ergeben hat. Du könntest auch eine andere Anzahl von Leerzeichen wählen, aber fast alle Python-Programmier nutzen 4 Leerzeichen, damit's gut aussieht. Ein einfaches Tab zählt auch wie 4 Leerzeichen, sofern dies in deinem Editor so eingestellt ist. Wenn du dich einmal entschieden hast, bleib dabei! Wenn du mit 4 Leerzeichen angefangen hast, solltest du alle weiteren Einrückungen auch mit 4 Leerzeichen machen, anderweitig könnte das Probleme verursachen. + +Nun sichere die Datei und führe sie noch einmal aus: + +{% filename %}command-line{% endfilename %} + +```python +$ python3 python_intro.py +It works! +``` + +Hinweis: Denk daran, dass Windows den 'python3'-Befehl nicht kennt. Falls du auf Windows arbeitest, verwende ab jetzt immer 'python', wenn in dieser Anleitung 'python3' steht. + +### Was passiert, wenn eine Bedingung nicht wahr (not True) ist? + +In den vorigen Beispielen wurde Code ausgeführt, wenn eine vorhergehende Bedingung True (wahr) ergab. Aber Python kennt auch `elif`- und `else`-Anweisungen: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 5 > 2: + print('5 ist wirklich größer als 2') +else: + print('5 ist nicht größer als 2') +``` + +Wenn dies ausgeführt wird, wird es anzeigen: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + 5 ist wirklich größer als 2 + + +Wenn 2 größer als 5 wäre, würde die zweite Anweisung (die nach dem else) ausgeführt. Schauen wir uns nun an, wie `elif` funktioniert: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +und ausgeführt erhalten wir: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hey Sonja! + + +Hast du bemerkt, was passiert ist? `elif` lässt dich zusätzliche Bedingungen hinzufügen, die geprüft werden, falls die vorherige fehlschlägt. + +Du kannst so viele `elif`-Bedingungen nach der anfänglichen `if`-Anweisung hinzufügen, wie du magst. Zum Beispiel: + +{% filename %}python_intro.py{% endfilename %} + +```python +volume = 57 # "volume" ist Englisch für "Lautstärke" +if volume < 20: + print("Das ist etwas leise.") +elif 20 <= volume < 40: + print("Das ist gut für Hintergrund-Musik.") +elif 40 <= volume < 60: + print("Perfekt, ich kann alle Details hören.") +elif 60 <= volume < 80: + print("Gut für Partys.") +elif 80 <= volume < 100: + print("Etwas laut!") +else: + print("Mir tun die Ohren weh! :(") +``` + +Python läuft durch jeden Test der Reihe nach und gibt dann aus: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Perfekt, ich kann alle Details hören. + + +## Kommentare + +Kommentare sind Zeilen, die mit `#` beginnen. Du kannst nach dem `#` schreiben, was auch immer du willst, und Python wird es ignorieren. Kommentare können deinen Code für andere Leute einfacher zu verstehen machen. + +Schauen wir, wie das aussieht: + +{% filename %}python_intro.py{% endfilename %} + +```python +# Ändert die Lautstärke, wenn sie zu leise oder zu laut ist +if volume < 20 or volume > 80: + volume = 50 + print("So ist's besser!") +``` + +Du musst nicht für jede Codezeile einen Kommentar schreiben, aber Kommentare sind nützlich um zu erklären, wieso dein Code etwas macht, oder um zusammenzufassen, wenn er etwas Komplexes tut. + +### Zusammenfassung + +In den letzten paar Übungen hast du gelernt: + +- **Vergleiche vorzunehmen** – in Python kannst du Vergleiche mit den folgenden Operatoren `>`, `>=`, `==`, `<=`, `<` sowie `and` und `or` vornehmen +- **Boolsche Datentypen** zu verwenden – dies sind Objekte, die nur zwei Werte annehmen können: `True` bzw. `False` +- **Dateien zu speichern** – also Programmcode in Dateien abzulegen, so dass du auch umfangreichere Programme schreiben kannst. +- **if … elif … else** – Anweisungen, die dir erlauben, bestimmte Programmteile nur auszuführen, wenn bestimmte Bedingungen erfüllt sind. +- **Kommentare** – Zeilen, die Python nicht ausführt und die dir ermöglichen deinen Code zu dokumentieren + +Zeit für den letzten Teil dieses Kapitels! + +## Deine eigenen Funktionen! + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) behandelt. + +Erinnerst du dich an Funktionen wie `len()`, die du in Python aufrufen kannst? Prima! Du wirst nun lernen, eigene Funktionen zu schreiben! + +Eine Funktion ist eine Folge von Anweisungen, die Python ausführen soll. Jede Funktions-Definition beginnt mit dem Schlüsselwort (engl. "Keyword") `def`, bekommt einen Namen und kann Argumente (manchmal auch "Parameter" genannt) haben. Probieren wir's aus! Ersetze den Code in der Datei **python_intro.py** mit dem folgenden: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hallo(): + print("Halli-hallo!") + print("Wie geht's?") + +hallo() +``` + +Und schon hast du deine erste Funktion erstellt! + +Nun fragst du dich vielleicht, warum wir am Ende der Datei den Namen der Funktion nochmal hingeschrieben haben. Wenn wir `def hallo():` und die darauf folgenden, eingerückten Zeilen schreiben, dann schreiben wir Anweisungen, was die `hallo()` Funktion tun soll. Python wird diese Anweisungen lesen und speichern, die Funktion jedoch noch nicht ausführen. Um Python zu sagen, dass wir die Funktion ausführen wollen, müssen wir die Funktion mit `hallo()` aufrufen. Python liest und führt die Datei von oben nach unten aus, daher müssen wir die Funktion in der Datei erst definieren bevor wir sie aufrufen. + +Schauen wir, was passiert, wenn wir die Datei ausführen: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Halli-hallo! + Wie geht's? + + +Falls das nicht funktionert hat, keine Panik! Die Ausgabe wird dir dabei helfen, herauszufinden wieso: + +- Wenn du einen `NameError` erhältst, hast du dich vermutlich irgendwo im Code vertippt. Prüfe also, ob du bei der Funktionsdefinition `def hallo():` und beim Funktionsaufruf `hallo()` den Funktionsnamen gleich geschrieben hast. +- Wenn du einen `IndentationError` bekommst, prüfe, ob beide `print`-Zeilen die gleichen Whitespaces am Zeilenanfang haben: Python will den ganzen Code in einer Funktion hübsch ausgerichtet haben. +- Wenn du gar keine Ausgabe erhältst, stelle sicher, dass `hallo()` am Datei-Ende *nicht* eingerückt ist. Wenn es eingerückt ist, ist dieser Aufruf selbst Teil der Funktion und sie wird gar nicht ausgeführt. + +Als Nächstes bauen wir Funktionen mit sogenannten Argumenten. Wir werden das gerade gebaute Beispiel benutzen – eine Funktion, die die ausführende Person begrüßt – aber diesmal mit Namen: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hallo(name): +``` + +Wie du siehst, geben wir der Funktion jetzt einen Parameter, den wir `name` nennen: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hallo(name): + if name == 'Ola': + print('Hallo Ola!') + elif name == 'Sonja': + print('Hallo Sonja!') + else: + print('Hallo Unbekannte(r)!') + +hallo() +``` + +Denk daran: Die `print`-Funktion ist 4 Leerzeichen innerhalb der `if`-Anweisung eingerückt. Das ist sinnvoll, da die Funktion ausgeführt wird, wenn die Bedingung eintritt. Mal sehen, wie das jetzt funktioniert: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + hallo() + TypeError: hallo() missing 1 required positional argument: 'name' + + +Hoppla, ein Fehler. Zum Glück gibt uns Python eine recht nützliche Fehlermeldung. Diese besagt, dass die Funktion `hallo()` (welche wir definiert haben) ein erforderliches Argument (namens `name`) hat und dass wir vergessen haben, dieses beim Funktionsaufruf mitzugeben. Lass uns das am unteren Ende der Datei schnell beheben: + +{% filename %}python_intro.py{% endfilename %} + +```python +hallo("Ola") +``` + +Und wir führen sie erneut aus: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hallo Ola! + + +Und wenn wir den Namen ändern? + +{% filename %}python_intro.py{% endfilename %} + +```python +hallo("Sonja") +``` + +Und ausgeführt: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hallo Sonja! + + +Nun, was denkst du, wird passieren, wenn du einen anderen Namen dort hinein schreibst? (Weder Ola noch Sonja.) Probier es aus und schau, ob du richtig liegst. Es sollte das Folgende herauskommen: + +{% filename %}command-line{% endfilename %} + + Hallo Unbekannte(r)! + + +Das ist genial, oder? Auf diese Weise musst du dich nicht jedesmal wiederholen, wenn du den Namen der Person änderst, die die Funktion grüßen soll. Und das ist genau der Grund, warum wir Funktionen brauchen – du willst auf keinem Fall deinen Code wiederholen! + +Lass uns noch etwas Schlaueres probieren – es gibt schließlich mehr als zwei Namen und für jeden eine eigene Bedingung aufzuschreiben, wäre ziemlich aufwendig, oder? Ersetze also deinen Code in der Datei durch den folgenden: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hallo(name): + print('Hallo ' + name + '!') + +hallo("Rachel") +``` + +Lass uns den Code aufrufen: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hallo Rachel! + + +Herzlichen Glückwunsch! Du hast gerade gelernt, wie du Funktionen schreibst! :) + +## Schleifen + +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) behandelt. + +Dies ist bereits der letzte Teil. Das ging doch schnell, oder? :) + +Programmierer wiederholen sich nicht gerne. Beim Programmieren geht es darum, Dinge zu automatisieren. Wir wollen also nicht jede Person mit ihrem Namen manuell grüßen müssen, oder? Für so etwas kommen Schleifen gelegen. + +Erinnerst du dich noch an Listen? Lass uns eine Liste mit Mädchennamen erstellen: + +{% filename %}python_intro.py{% endfilename %} + +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + +Wir wollen alle mit ihrem Namen grüßen. Wir besitzen bereits die `hallo`-Funktion, um dies zu tun, also lass sie uns in einer Schleife verwenden: + +{% filename %}python_intro.py{% endfilename %} + +```python +for name in girls: +``` + +Die `for`-Anweisung verhält sich ähnlich wie die `if`-Anweisung; Code unter beiden muss 4 Leerzeichen eingerückt werden. + +Hier ist der vollständige Code für die Datei: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hallo(name): + print('Hallo ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'du'] +for name in girls: + hallo(name) + print('Nächstes Mädchen') +``` + +Und wenn wir es ausführen: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hallo Rachel! + Nächstes Mädchen + Hallo Monica! + Nächstes Mädchen + Hallo Phoebe! + Nächstes Mädchen + Hallo Ola! + Nächstes Mädchen + Hallo du! + Nächstes Mädchen + + +Wie du sehen kannst, wird alles, was du innerhalb einer `for`-Anweisung eingerückt hast, für jedes Element der Liste `girls` wiederholt. + +Du kannst auch `for` auf Ganzzahlen beziehen, wenn du die `range`-Funktion benutzt: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Das würde ausgeben: + +{% filename %}command-line{% endfilename %} + + 1 + 2 + 3 + 4 + 5 + + +`range` ist eine Funktion, die eine Liste von aufeinander folgenden Zahlen erschafft (die Randwerte werden von dir als Argumente bereitgestellt). + +Beachte, dass der zweite der Werte, die du als Argumente übergibst, nicht in der Liste enthalten ist, die von Python ausgegeben wird. (Das bedeutet, dass `range(1, 6)` von 1 bis 5 zählt, aber nicht die Zahl 6 enthält). Das liegt daran, dass "range" halboffen ist, was wiederum bedeutet, dass es den ersten Wert enthält, aber nicht den letzten. + +## Zusammenfassung + +Das ist alles. **Du rockst total!** Das war ein kniffliges Kapitel, du darfst also ruhig stolz auf dich sein. Wir sind definitiv stolz auf dich und darauf, dass du es so weit geschafft hast! + +Wenn du zum offiziellen und vollständigen Python-Tutorial willst, besuche https://docs.python.org/3/tutorial/. Dort gibt's (bislang jedoch noch nicht auf Deutsch) eine gründlichere und umfassendere Einführung in diese Programmiersprache. Viel Erfolg! :) + +Bevor du zum nächsten Kapitel übergehst, mach kurz 'was anderes – streck dich, lauf etwas 'rum, ruh' deine Augen aus. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/de-DE/template_extending/README.md b/de-DE/template_extending/README.md new file mode 100644 index 00000000000..5362ae574b6 --- /dev/null +++ b/de-DE/template_extending/README.md @@ -0,0 +1,151 @@ +# Erweiterung der Templates + +Eine weitere praktische Sache von Django ist das **template extending**, Erweiterungen des Templates. Was bedeutet das? Damit kannst du Teile deines HTML-Codes für andere Seiten deiner Website nutzen. + +Templates helfen, wenn du die selben Informationen oder das selbe Layout an mehreren Stellen verwenden willst. Du musst dich so nicht in jeder Datei wiederholen. Und wenn du etwas ändern willst, dann musst du es nicht in jedem einzelnen Template tun, sondern nur in einem! + +## Ein Basis-Template erstellen + +Ein Basis-Template ist das grundlegende Template, welches dann auf jeder einzelnen Seite deiner Website erweitert wird. + +Wir erstellen jetzt eine `base.html`-Datei in `blog/templates/blog/`: + + blog + └───templates +     └───blog +             base.html +             post_list.html + + +Öffne sie im Code-Editor, kopiere alles von `post_list.html` und füge es wie folgt in die `base.html`-Datei ein: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Dann ersetze in `base.html` den gesamten `` (alles zwischen `` und ``) hiermit: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}Vielleicht hast du bemerkt, dass das alles von `{% for post in posts %}` bis `{% endfor %}` mit dem Folgenden ersetzt: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +Aber warum? Du hast gerade einen `block` erstellt! Du hast den Template-Tag `{% block %}` benutzt, um einen Bereich zu schaffen, der HTML aufnehmen kann. Dieses HTML kommt aus einem anderen Template, welches das Template hier (`base.html`) erweitert. Wir zeigen dir gleich, wie das geht. + +Speichere nun die Datei `base.html` und öffne wieder `blog/templates/blog/post_list.html` im Code-Editor. {% raw %}Du löschst alles oberhalb von `{% for post in posts %}` und unterhalb von `{% endfor %}`. Wenn du das gemacht hast, sieht die Datei so aus:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +Dieser Teil unseres Templates soll nun das Basis-Template erweitern. Wir müssen daher Block-Tags ergänzen! + +{% raw %}Deine Block-Tags müssen mit den Tags in der `base.html`-Datei übereinstimmen. Stelle sicher, dass die Block-Tags den ganzen Code deines content-Blocks umschließen. Um das zu erreichen, umschließt du ihn mit `{% block content %}` und `{% endblock %}`. So hier:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Nur eine Sache noch. Wir müssen die beiden Templates miteinander verknüpfen. Darum geht es ja bei der Template-Erweiterung! Dafür ergänzen wir einen Tag für Erweiterung (extends tag) ganz oben in der Datei. Und zwar so: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Das war's! Speichere die Datei und probier aus, ob deine Website noch richtig funktioniert. :) + +> Wenn du den Fehler `TemplateDoesNotExist` erhältst, dann heißt das, dass es die Datei `blog/base.html` nicht gibt und dass `runserver` in der Konsole läuft. Halte ihn an (durch Drücken von Ctrl+C bzw. Strg+C – Control- und die C-Taste gleichzeitig) und starte ihn neu, indem du den Befehl `python manage.py runserver` ausführst. \ No newline at end of file diff --git a/de-DE/whats_next/README.md b/de-DE/whats_next/README.md new file mode 100644 index 00000000000..caa79e6cb03 --- /dev/null +++ b/de-DE/whats_next/README.md @@ -0,0 +1,43 @@ +# Wie geht es weiter? + +Herzlichen Glückwunsch! **Du bist der Hammer!** Wir sind echt stolz! <3 + +### Was jetzt? + +Mach eine Pause und entspanne! Du hast gerade etwas wirklich Großes geleistet. + +Und dann folge Django Girls doch auf [Facebook](http://facebook.com/djangogirls) oder [Twitter](https://twitter.com/djangogirls), um auf dem Laufenden zu bleiben. + +### Könnt ihr weiteres Lernmaterial empfehlen? + +Ja! Es gibt *sehr* viele Online-Ressourcen zum Erlernen aller möglichen Programmierfähigkeiten – es kann ziemlich entmutigend sein, herauszufinden, was man als Nächstes machen sollte, aber wir helfen dir dabei. Was auch immer du für Interessen hattest, bevor du zu Django Girls gekommen bist und was auch immer du für Interessen während des Tutorials entwickelt hast, hier sind einige kostenfreie Ressourcen (oder solche mit größeren kostenlosen Teilen), die du nutzen kannst, um auf deinem Weg voranzukommen. + +#### Django + +- Unser anderes Buch, [Django Girls Tutorial: Erweiterungen](https://tutorial-extensions.djangogirls.org/) +- [Das offizielle Django-Tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Video-Lektionen "Getting Started With Django"](http://www.gettingstartedwithdjango.com/) +- Spezialisierung [Django for Everybody](https://www.coursera.org/specializations/django) – einige Video-Lektionen können kostenlos getestet werden und du kannst ein Coursera-Zertifikat erlangen, wenn du diesen Kurs belegst + +#### HTML, CSS und JavaScript + +- [Web-Development-Kurs auf Codeacademy](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Python-Kurs auf Codecademy](https://www.codecademy.com/learn/learn-python) +- [Googles Python-Kurs](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) – die ersten Übungen sind kostenlos +- [New Coder Tutorials](http://newcoder.io/tutorials/) – eine Vielzahl von praktischen Beispielen, wie Python verwendet werden kann +- [edX](https://www.edx.org/course?search_query=python) – die meisten Kurse kannst du kostenfrei testen, aber wenn du ein Zertifikat oder Credits für eine Weiterbildung erhalten willst, dann kostet das etwas +- [Courseras Python-Spezialisierung](https://www.coursera.org/specializations/python) – einige Video-Lektionen können kostenlos getestet werden und du kannst ein Coursera-Zertifikat erlangen, wenn du diesen Kurs belegst +- [Python for Everybody](https://www.py4e.com/) - eine kostenlose und offene Version der Coursera-Python-Spezialisierung + +#### Mit Daten arbeiten + +- [Der Data-Science-Kurs von Codecademy](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – die meisten Kurse kannst du kostenfrei testen, aber wenn du ein Zertifikat oder Credits für eine Weiterbildung erhalten willst, dann kostet das etwas +- [Dataquest](https://www.dataquest.io/) – die ersten 30 "Missionen" sind frei + +Wir sind gespannt darauf, was du als Nächstes baust! \ No newline at end of file diff --git a/de/README.md b/de/README.md index 324783fea2c..619388aaebb 100644 --- a/de/README.md +++ b/de/README.md @@ -1,22 +1,28 @@ -# Django Girls Tutorial +# Django Girls Anleitung [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) -> Dieses Werk ist unter der Creative Commons Attribution-ShareAlike 4.0 International License lizensiert. Eine Kopie dieser Lizenz findest du auf http://creativecommons.org/licenses/by-sa/4.0/ +> Dieses Werk ist unter der Creative Commons Attribution-ShareAlike 4.0 International License lizensiert. Eine Kopie dieser Lizenz finden Sie auf http://creativecommons.org/licenses/by-sa/4.0/ + +## Willkommen + +Willkommen bei der Django Girls Anleitung! Wir freuen uns, dass du hier bist :) In dieser Anleitung schauen wir gemeinsam unter die Haube der Technologien im Internet, geben dir einen Einblick in die Bits und Bytes, die zusammen das Internet bilden, wie wir es heute kennen. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) ## Einleitung -Hattest du auch schon einmal das Gefühl, dass Technik in der Welt immer wichtiger wird und du da nicht ganz mithalten kannst? Wolltest du schon immer einmal eine Website bauen, aber hattest dann nicht genug Motivation, damit anzufangen? Hast du dir irgendwann schon einmal gedacht, dass die Computerwelt zu kompliziert für dich ist, so dass du noch nicht einmal den Versuch unternommen hast, dort selbst etwas zu tun? +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Wolltest du schon immer einmal eine Website bauen, aber hattest dann nicht genug Motivation, damit anzufangen? Hast du dir irgendwann schon einmal gedacht, dass die Computerwelt zu kompliziert für dich ist, so dass du noch nicht einmal den Versuch unternommen hast, dort selbst etwas zu tun? Dann haben wir hier gute Neuigkeiten für dich! Programmieren ist nicht so schwer, wie du denkst und wir zeigen dir hier, wie viel Spaß es machen kann. -Dieses Tutorial wird dich nicht auf zauberhafte Weise in eine Programmiererin verwandeln. Wenn du gut darin sein willst, brauchst du Monate oder sogar Jahre des Lernens und Übens. Aber wir wollen dir zeigen, dass Programmieren oder Webseitenerstellen nicht so kompliziert ist, wie es scheint. Wir versuchen, dir auf einfache Art verschiedene, kleine Teile zu zeigen, so dass du davon nicht eingeschüchtert wirst. +This tutorial will not magically turn you into a programmer. Wenn du gut darin sein willst, brauchst du Monate oder sogar Jahre des Lernens und Übens. Aber wir wollen dir zeigen, dass Programmieren oder Webseitenerstellen nicht so kompliziert ist, wie es scheint. Wir versuchen, dir auf einfache Art verschiedene, kleine Teile zu zeigen, so dass du davon nicht eingeschüchtert wirst. Wir hoffen, dass du danach diese Technik und Technologien so sehr mögen wirst wie wir! ## Was lernst du in diesem Tutorial? -Wenn du mit dem Tutorial fertig bist, hast du eine einfache, aber funktionierende Webanwendung: deinen eigenen Blog. Wir zeigen dir, wie man ihn online stellt, andere können dein Werk also sehen! +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! Es wird (in etwa) so aussehen: @@ -24,20 +30,22 @@ Es wird (in etwa) so aussehen: > Wenn du allein mit diesem Tutorial arbeitest und keinen Coach in der Nähe hast, kannst du in diesem Chat nachfragen, wenn du ein Problem hast: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). Wir haben unsere Coaches und frühere Teilnehmer unserer Workshops gebeten, hin und wieder dort vorbei zu schauen und anderen mit dem Tutorial zu helfen! Hab keine Angst, dort deine Fragen zu stellen! -Okay, [lass uns ganz am Anfang anfangen...](./how_the_internet_works/README.md) +OK, [let's start at the beginning…](./how_the_internet_works/README.md) + +## Following the tutorial at home -## Mit dem Tutorial zu Hause arbeiten +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. -Na klar ist es aufregend, bei einem Django Girls Workshop dabei zu sein, aber es ist auch verständlich, dass das nicht immer klappt. Deswegen möchten wir es dir erleichtern, das Tutorial auch von Hause aus zu erarbeiten. Dafür erstellen wir Videos zu einzelnen Themen, die dir helfen können, die Inhalte besser zu verstehen. Wir arbeiten noch daran, aber einige sind schon verfügbar und du kannst sie dir gern auf dem "[Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed)"-YouTube-Channel anschauen. +In every chapter already covered, there is a link that points to the correct video. ## Über uns und wie du mithelfen kannst -Dieses Tutorial wird von [DjangoGirls](http://djangogirls.org/) betreut. Solltest du Fehler finden oder das Tutorial aktualisieren wollen, dann folge den [Richtlinien zum Mitarbeiten](https://github.com/DjangoGirls/tutorial/blob/master/CONTRIBUTING.md). +Dieses Tutorial wird von [DjangoGirls](https://djangogirls.org/) betreut. Solltest du Fehler finden oder das Tutorial aktualisieren wollen, dann folge den [Richtlinien zum Mitarbeiten](https://github.com/DjangoGirls/tutorial/blob/master/CONTRIBUTING.md). -## Möchtest du uns helfen, das Tutorial in andere Sprachen zu übersetzen? +## Would you like to help us translate the tutorial into other languages? -Zur Zeit haben wir die Übersetzungen auf der crowdin.com Plattform: +Currently, translations are being kept on crowdin.com platform at: https://crowdin.com/project/django-girls-tutorial -Sollte deine Sprache nicht aufgeführt sein, dann öffne ein neues [Issue](https://github.com/DjangoGirls/tutorial/issues/new), mit der betreffenden Sprache, dann können wir sie hinzufügen. +If your language is not listed on [crowdin](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/de/SUMMARY.md b/de/SUMMARY.md index 51d4ba518f2..6e8d88c782d 100644 --- a/de/SUMMARY.md +++ b/de/SUMMARY.md @@ -1,26 +1,27 @@ # Zusammenfassung -* [Einleitung](README.md) -* [Installation](installation/README.md) -* [Wie das Internet funktioniert](how_the_internet_works/README.md) -* [Einführung in die Kommandozeile](intro_to_command_line/README.md) -* [Python-Installation](python_installation/README.md) -* [Der Editor](code_editor/README.md) -* [Einführung in Python](python_introduction/README.md) -* [Django - Was ist das?](django/README.md) -* [Django Installation](django_installation/README.md) -* [Dein erstes Django-Projekt!](django_start_project/README.md) -* [Django Models](django_models/README.md) -* [Django Administration](django_admin/README.md) -* [Veröffentlichen!](deploy/README.md) -* [Django URLs](django_urls/README.md) -* [Django Views - Zeit zum Gestalten!](django_views/README.md) -* [Einführung in HTML](html/README.md) -* [Django ORM (Querysets)](django_orm/README.md) -* [Dynamische Daten in Templates](dynamic_data_in_templates/README.md) -* [Django Templates](django_templates/README.md) -* [CSS - mach es hübsch!](css/README.md) -* [Template Erweiterung](template_extending/README.md) -* [Erweitere deine Anwendung](extend_your_application/README.md) -* [Django Formulare](django_forms/README.md) -* [Was kommt als Nächstes?](whats_next/README.md) +* [Einleitung](README.md) +* [Installation](installation/README.md) +* [Installation (Chromebook)](chromebook_setup/README.md) +* [Wie funktioniert das Internet](how_the_internet_works/README.md) +* [Einführung in die Kommandozeile](intro_to_command_line/README.md) +* [Python-Installation](python_installation/README.md) +* [Der Code-Editor](code_editor/README.md) +* [Einführung in Python](python_introduction/README.md) +* [Django - Was ist das?](django/README.md) +* [Django Installation](django_installation/README.md) +* [Dein erstes Django-Projekt!](django_start_project/README.md) +* [Django Models](django_models/README.md) +* [Django Administration](django_admin/README.md) +* [Veröffentlichen!](deploy/README.md) +* [Django URLs](django_urls/README.md) +* [Django views - leg los!](django_views/README.md) +* [Einführung in HTML](html/README.md) +* [Django ORM (Querysets)](django_orm/README.md) +* [Dynamische Daten in Templates](dynamic_data_in_templates/README.md) +* [Django Templates](django_templates/README.md) +* [CSS - mach es hübsch](css/README.md) +* [Erweiterung der Templates](template_extending/README.md) +* [Erweitere deine Anwendung](extend_your_application/README.md) +* [Django Formulare](django_forms/README.md) +* [Wie geht es weiter?](whats_next/README.md) \ No newline at end of file diff --git a/de/chromebook_setup/README.md b/de/chromebook_setup/README.md new file mode 100644 index 00000000000..0340021beb5 --- /dev/null +++ b/de/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook-Installation + +> **Hinweis** Wenn du die Installation bereits gemacht hast, kannst du direkt zur [Einführung in Python](../python_introduction/README.md) gehen. + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/de/chromebook_setup/instructions.md b/de/chromebook_setup/instructions.md new file mode 100644 index 00000000000..c53224bd8e8 --- /dev/null +++ b/de/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +Du kannst diese [Section](http://tutorial.djangogirls.org/en/installation/#install-python) direkt überspringen, falls du kein Chromebook benutzt. Wenn du eins benutzt wird deine Installation ein wenig anders sein. Du kannst den Rest der Installationsanweisungen ignorieren. + +### 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 the software. Während des Tutorials wird dir Cloud 9 als dein *lokaler Rechner* dienen. Du wirst die gleichen Befehle ausführen, wie deine Klassenkameradinnin, die OS X, Ubuntu oder Windows benutzen, jedoch ist dein Terminal verbunden mit einem Computer, der von Cloud 9 gehostet wird. + +1. Installiere Cloud 9 aus dem [Chrome web store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Gehe auf [c9.io](https://c9.io) +3. Erstelle dir einen Account +4. Klicke auf *Create a New Workspace* +5. Gib ihm den Namen *django-girls* +6. Wähle *Blank* aus( das zweite von links in der untersten Reihe mit dem orangen Logo) + +Jetzt solltest du ein Interface mit Sidebar, ein grosses Fenster mit Text und am unteren Rand ein Feld sehen, das wie folgt aussieht: + +{% filename %}Cloud 9{% endfilename %} + + deinbenutzername:~/workspace $ + + +This bottom area is your *terminal*, where you will give the computer Cloud 9 has prepared for your instructions. You can resize that window to make it a bit bigger. + +### Virtuelle Umgebung + +Eine virtuelle Umgebung (auch virtualenv genannt) ist ein privater Behälter, in den wir nützlichen Code packen können, um an einem Projekt arbeiten zu können. Wir benutzen diese, um Code für verschiedene Projekte getrennt aufzubewahren, damit diese nicht vermischt werden. + +Führe im Terminal den folgenden Code aus( das Terminal befindet sich am unteren Rand des Cloud 9 Interface): + +{% filename %}Cloud 9{% endfilename %} + + sudo apt update + sudo apt install python3.6-venv + + +Wenn du Probleme hast frag deinen Coach nach Hilfe. + +Als nächstes führe die folgenden Befehle aus: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.0 + + +(beachte, dass wir im letzten Befehl eine Tilde gefolgt von einem Gleichheitssymbol benutzen: ~=). + +### Github + +Erstelle einen [Github](https://github.com) Account. + +### PythonAnywhere + +Das Django Girls tutorial beinhaltet einen Teil zu Deployment. Beim Deployment nimmst du den Code, der deiner Web Anwendung zu Grunde liegt und packst ihn auf einen öffentlich zugänglichen Computer (Server), damit auch andere Leute deine Arbeit betrachten können. + +Dieser Teil ist ein bisschen seltsam, wenn du ihn auf einem Chromebook ausführst, da er bereits nur in der Cloud ist( im Gegensatz zu einem Laptop). Es ist aber trotzdem sinnvoll mitzumachen, wir stellen uns dann einfach unseren Cloud 9 Arbeitsplatz als "work in progress" vor und Python Anywhere als Platz auf dem wir unser Projekt vorführen können. + +Deshalb solltest du dich auf [www.pythonanywhere.com](https://www.pythonanywhere.com) für einen Python Anywhere Account anmelden. \ No newline at end of file diff --git a/de/code_editor/README.md b/de/code_editor/README.md index a5f09e4cf20..26c7539741e 100644 --- a/de/code_editor/README.md +++ b/de/code_editor/README.md @@ -1,7 +1,11 @@ -# Der Editor +# Der Code-Editor -Gleich geht's los! Du wirst deine erste Zeile Programmcode schreiben! Daher ist es jetzt an der Zeit, einen entsprechenden Editor herunterzuladen. +> Für die Leser zu Hause: Dieses Kapitel wird im Video [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) behandelt. -> **Hinweis:** Es kann sein, dass du diesen Schritt bereits im Kapitel "Installation" erledigt hast. In diesem Fall kannst du direkt zum nächsten Kapitel übergehen. +Gleich geht's los! Du wirst deine erste Zeile Programmcode schreiben! Daher ist es jetzt an der Zeit, einen entsprechenden Editor herunterzuladen! -{% include "/code_editor/instructions.md" %} +> **Hinweis** Wenn du ein Chromebook verwendest, überspringe bitte dieses Kapitel und folgen den Anweisungen im [Chromebook Setup](../chromebook_setup/README.md). +> +> **Hinweis:** Es kann sein, dass du diesen Schritt bereits in dem Kapitel "Installation" erledigt hast. In diesem Fall kannst du direkt zum nächsten Kapitel übergehen! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/de/code_editor/instructions.md b/de/code_editor/instructions.md index fe8d0da3867..cc5385eb469 100644 --- a/de/code_editor/instructions.md +++ b/de/code_editor/instructions.md @@ -1,4 +1,4 @@ -Es gibt viele verschiedene Editoren. Welcher für dich am besten ist, ist weitestgehend Geschmackssache. Die meisten Python-Programmiererinnen verwenden komplexe, aber extrem leistungsfähige IDEs (Integrated Development Environments), z. B. PyCharm. Für Anfängerinnen sind diese jedoch wahrscheinlich weniger gut geeignet. Unsere Empfehlungen sind ebenso leistungsfähig, aber viel einfacher zu bedienen. +Es gibt viele verschiedene Editoren. Welcher für Dich am besten ist, ist weitestgehend Geschmackssache. Die meisten Python-Programmiererinnen verwenden komplexe, aber extrem leistungsfähige IDEs (Integrated Development Environments), z. B. PyCharm. Für Anfängerinnen sind diese jedoch wahrscheinlich weniger gut geeignet. Unsere Empfehlungen sind ebenso leistungsfähig, aber viel einfacher zu bedienen. Unsere Vorschläge siehst du unten. Aber fühl dich ganz frei, deine Trainerin zu fragen, was ihre Vorlieben sind - wenn sie sich mit dem Editor auskennt, wird es leichter sein, Hilfe zu erhalten. @@ -6,19 +6,19 @@ Unsere Vorschläge siehst du unten. Aber fühl dich ganz frei, deine Trainerin z Gedit ist ein kostenloser Open-Source-Editor. Es gibt ihn für alle Betriebssysteme. -[Hier herunterladen:](https://wiki.gnome.org/Apps/Gedit#Download) +[Du kannst ihn hier herunterladen](https://wiki.gnome.org/Apps/Gedit#Download) -## Sublime Text 2 +## Sublime Text 3 -Sublime Text ist ein sehr beliebter Editor mit einem kostenlosen Testzeitraum. Er ist einfach zu installieren und zu verwenden, und er ist für alle Betriebssysteme verfügbar. +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. -[Hier herunterladen:](http://www.sublimetext.com/2) +[Du kannst ihn hier herunterladen](https://www.sublimetext.com/3) ## Atom -Atom ist ein ganz neuer Code-Editor, der von [GitHub](http://github.com/) ins Leben gerufen wurde. Er ist kostenlos, quelloffen (Open Source), einfach zu installieren und einfach zu bedienen. Atom ist verfügbar für Windows, OS X und Linux. +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. -[Hier herunterladen:](https://atom.io/) +[Du kannst ihn hier herunterladen](https://atom.io/) ## Warum installieren wir einen Code-Editor? @@ -28,4 +28,4 @@ Erstens muss Code "plain text" (unformatierter Text) sein. Das Problem mit Progr Ein weiterer Grund ist, dass Code-Editoren (bisweilen auch Programmier- oder Text-Editoren genannt) auf das Bearbeiten von Programm-Code spezialisiert sind und Funktionen aufweisen, die normale Textverarbeitungen nicht haben. Beispielsweise sogenanntes "Syntax-Highlighting", also farbliches Hervorheben bestimmter Code-Stellen, oder auch das automatische Schließen von Klammern und vieles mehr. -Einige davon werden wir später in Aktion sehen. Glaub uns: es wird nicht lange dauern, bis du deinen Code-Editor nicht mehr missen möchtest :) \ No newline at end of file +Einige davon werden wir später in Aktion sehen. Glaub uns: es wird nicht lange dauern, bis du deinen Code-Editor nicht mehr missen möchtest. :) \ No newline at end of file diff --git a/de/css/README.md b/de/css/README.md index dba188ef932..c2a3f8110d7 100644 --- a/de/css/README.md +++ b/de/css/README.md @@ -1,25 +1,27 @@ # CSS - mach es hübsch! -Unser Blog sieht immer noch ziemlich unfertig aus, oder? Zeit, das zu ändern! Dafür nutzen wir CSS. +Unser Blog sieht immer noch ziemlich unfertig aus, oder? Zeit das zu ändern! Dafür nutzen wir CSS. ## Was ist CSS? -Cascading Style Sheets (CSS) ist eine Sprache, die das Aussehen und die Formatierung einer Website beschreibt. Es handelt sich wie bei HTML um eine Auszeichnungssprache (Markup Language). Sie ist sowas wie das "Make-up" unserer Website ;). +Cascading Style Sheets (CSS) ist eine Sprache, die das Aussehen und die Formatierung einer Website beschreibt. Es handelt sich wie bei HTML um eine Auszeichnungssprache (Markup Language). Sie ist sowas wie das "Make-up" unserer Website. ;) -Aber wir wollen nicht wieder von vorne anfangen, nicht wahr? Ein weiteres Mal werden wir von dem profitieren, was andere Programmiererinnen vor uns erstellt und im Internet veröffentlicht haben. Das Rad neu zu erfinden, macht ja keinen Spaß. +Aber wir wollen nicht nochmal bei Null anfangen, oder? Einmal mehr werden wir etwas verwenden, dass ProgrammiererInnen entwickelt haben und gratis im Internet zur Verfügung stellen. Wir wollen ja nicht das Rad neu erfinden. ## Lass uns Bootstrap verwenden! -Bootstrap ist eines der bekanntesten HTML- und CSS-Frameworks für die Entwicklung von schönen Websites: http://getbootstrap.com/ +Bootstrap ist eines der bekanntesten HTML- und CSS-Frameworks für die Entwicklung von schönen Websites: https://getbootstrap.com/ -Bootstrap hat seinen Ursprung im Umfeld von Twitter und wird heute von Freiwilligen weltweit weiterentwickelt. +Es wurde ursprünglich von ProgrammiererInnen bei Twitter geschrieben. Heute wird es von Freiwilligen aus der ganzen Welt weiterentwickelt! ## Bootstrap installieren -Um Bootstrap zu installieren, musst du das Folgende in den ``-Bereich in deiner `HTML`-Datei einfügen (`blog/templates/blog/post_list.html`): +Um Bootstrap zu installieren, müssen Sie das hinzufügen, um Ihre ``in Ihre `Html`-Datei: -```html - +{% filename %}blog/templates/blog/post_list{% endfilename %} + +```html + ``` @@ -31,78 +33,85 @@ Sie sieht jetzt schon viel schöner aus! ## Statische Dateien in Django -Schlussendlich werden wir einen genaueren Blick auf die Dinge werfen, die wir bisher **statische Dateien** genannt haben. Statische Dateien sind Bilder und dein CSS-Code. Diese Dateien sind nicht dynamisch, sie reagieren nicht auf Anfragen auf der Nutzerseite und sehen für jeden gleich aus. +Schlussendlich werden wir einen genaueren Blick auf die Dinge werfen, die wir bisher **statische Dateien** genannt haben. Statische Dateien sind alle deine CSS- und Bilddateien. Ihr Inhalt hängt nicht vom Requestkontext ab sondern gilt für alle Benutzer gleichermassen. ### Wohin kommen die statischen Dateien für Django -Wie du gesehen hast, als wir `collectstatic` auf dem Server ausgeführt haben, weiß Django bereits, wo die statischen Dateien für die eingebaute `admin`-App zu finden sind. Nun müssen wir nur ein paar statische Dateien für unsere eigene App, `blog`, hinzufügen. +Django weiss schon wo die statischen Dateien für die integrierte "admin" App zu finden sind. Wir müssen nur noch die statischen Dateien für unsere `blog` App hinzufügen. Dies tun wir, indem wir einen Ordner namens `static` in der Blog-App erstellen: -``` -djangogirls -├── blog -│ ├── migrations -│ └── static -└── mysite -``` + djangogirls + ├── blog + |     ├── migrationen + |     ├── statisch + |     └── vorlagen + └── meineseite + -Django findet automatisch alle Ordner mit dem Namen "static" in allen Ordnern unserer Apps und ist in der Lage, ihre Inhalte als statische Dateien zu nutzen. +Django findet automatisch jede datei mit dem namen "static" in jeder ihrer apps ordner. Danach wird er in der lage sein ihr Inhalt als statische dateien zu benutzen. ## Deine erste CSS-Datei! -Nun erstellen wir eine CSS-Datei, um deiner Website deinen eigenen Stil zu verleihen. Erstelle ein neues Verzeichnis namens `css` in deinem `static`-Verzeichnis. Dann erstelle eine neue Datei namens `blog.css` in diesem `css`-Verzeichnis. Fertig? +Lassen Sie uns jetzt eine CSS-Datei erstellen, um einen eigenen Stil zu Ihrer Webseite hinzuzufügen. Erstelle ein neues Verzeichnis namens `css` in deinem `static`-Verzeichnis. Dann erstelle eine neue Datei namens `blog.css` in diesem `css`-Verzeichnis. Fertig? -``` -djangogirls -└─── blog - └─── static - └─── css - └─── blog.css -``` + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + -Zeit, ein wenig CSS zu schreiben! Öffne die `blog/static/css/blog.css` Datei in einem Code-Editor. +Zeit ein wenig CSS zu schreiben! Öffne die `blog/static/css/blog.css` Datei in Deinem Code-Editor. -Wir werden an dieser Stelle nicht weiter auf das Anpassen und Erlernen von CSS eingehen, weil es ziemlich einfach ist und du es nach dem Workshop selbst erlernen kannst. Wir empfehlen diesen [Codeacademy HTML- & CSS-Kurs](http://www.codecademy.com/tracks/web), um alles zu erlernen, was du wissen musst, um deine Website mit CSS noch hübscher zu machen. +We won't be going too deep into customizing and learning about CSS here. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. -Aber lass uns wenigstens etwas Kleines probieren. Beispielsweise könnten wir die Farbe unserer Kopfzeile ändern. Computer benutzen spezielle Codes, um Farben zu verstehen. Ein solcher (hexadezimal) Code beginnt mit einer `#`, gefolgt von 6 Buchstaben (A-F) und Zahlen (0-9). Beispiele für solche Farbcodes findest du hier: http://www.colorpicker.com/. Du kannst auch [vordefinierte Farben](http://www.w3schools.com/cssref/css_colornames.asp) wie `red` und `green` benutzen. +Aber lass uns wenigstens etwas Kleines probieren. Beispielsweise könnten wir die Farbe unserer Kopfzeile ändern. Computer benutzen spezielle Codes, um Farben zu verstehen. Diese Codes beginnen mit `#` gefolgt von 6 Buchstaben (A-F) und nummern (0-9). Blau zum Beispiel ist `#0000FF`. Beispiele für solche Farbcodes findest Du hier: http://www.colorpicker.com/. Du kannst auch [vordefinierte Farben](http://www.w3schools.com/colors/colors_names.asp) wie `red` und `green` benutzen. In deiner `blog/static/css/blog.css` Datei änderst du den folgenden Code: +{% filename %}blog/static/css/blog.css{% endfilename %} + ```css h1 a { - color: #FCA205; +color: #FCA205; } ``` -`h1 a` ist ein CSS-Selektor. Das bedeutet, dass wir jedem `a`-Element innerhalb eines `h1`-Elements unsere Stilvorgaben zuordnen (z. B. wenn wir in unserem Code so etwas wie `

link

` haben). In diesem Fall sagen wir, dass es seine Farbe in `#FCA205` ändern soll, was für Orange steht. Du kannst hier natürlich deine eigene Farbe angeben! +`h1 a` ist ein CSS-Selektor. Das bedeutet, sass wir unsere Styles auf alle `a` Elemente innerhalb von einem `h1` Element anwenden. Also wenn wir so etwas wie `

link

`, der `h1 a` stil wird gelten. In diesem Fall sagen wir, dass es seine Farbe in `#FCA205` ändern soll, was für Orange steht. Du kannst hier natürlich deine eigene Farbe angeben! -In einer CSS-Datei werden Stile für Elemente der HTML-Datei festgelegt. Die Elemente werden durch den Elementnamen (in der Regel `a`, `h1`, `body`), das Attribut `class` oder das Attribut `id` bestimmt. Klassen (`class`) und IDs (`id`) sind Namen, die du den Elementen selbst gibst. Klassen definieren dabei Gruppen von Elementen und IDs verweisen auf bestimmte Elemente. Beispielsweise kann das folgende HTML-Tag von CSS mittels des Tag-Namens `a`, der Klasse `external_link` oder der ID `link_to_wiki_page` identifiziert werden: +In einer CSS-Datei werden Stile für Elemente der HTML-Datei festgelegt. Ein Weg HTML-Elemente zu identifizieren ist der Name des Elements. Du erinnerst dich vielleicht an diese Namen als 'Tags' aus dem HTML Kapitel. Zum Beispiel sind `a`, `h1` und `body` solche Elementnamen. Wir identifizieren Elemente auch über die Attribute `class` oder `id`. Klassen (`class`) und IDs (`id`) sind Namen, die du den Elementen selbst gibst. Klassen definieren dabei Gruppen von Elementen und IDs verweisen auf bestimmte Elemente. Du könntest zum Beispiel den folgenden Tag anhand des Elementnamen `a`, der Klasse `external_link` oder der Id `link_to_wiki_page` identifizieren: ```html -``` +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). -[Auf w3schools](http://www.w3schools.com/cssref/css_selectors.asp) erfährst du mehr über CSS-Selektoren. +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: -Dann musst du auch deiner HTML-Vorlage sagen, dass wir CSS aus einer externen Datei laden wollen. Öffne dazu die Datei `blog/templates/blog/post_list.html` und füge folgende Zeile ganz am Anfang der Datei an: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% load staticfiles %} ``` -Hier laden wir nur statische Dateien :). Dann fügst du zwischen `` und ``, nach dem Link auf die Bootstrap-CSS-Dateien die folgenden Zeilen an (Der Browser liest die Dateien in der Reihenfolge, wie sie angegeben sind, ein, so dass dein CSS möglicherweise den Code in den Bootstrap-Dateien überschreibt.): +We're just loading static files here. :) Between the `` and `` tags, after the links to the Bootstrap CSS files, add this line: -```html +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html ``` -Wir haben unserer Vorlage gerade gesagt, wo sich die CSS-Datei befindet. +Der Browser liest die Dateien in der Reihenfolge in der sie im File stehen. Darum müssen wir sicherstellen, dass die Zeile am richtigen Ort steht. Otherwise the code in our file may be overriden by code in Bootstrap files. Wir haben unserer Vorlage gerade gesagt, wo sich die CSS-Datei befindet. Deine Datei sollte jetzt so aussehen: -```html -{% load staticfiles %} +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load staticfiles %} Django Girls blog @@ -132,29 +141,35 @@ OK, speicher die Datei und lade die Seite neu! Gut gemacht! Vielleicht wollen wir unserer Webseite etwas mehr Luft geben, indem wir den Abstand auf der linken Seite vergrößern? Probieren wir es aus! +{% filename %}blog/static/css/blog.css{% endfilename %} + ```css -body { - padding-left: 15px; +body { + padding-left: 15px; } ``` -Füge dies zu deinem CSS hinzu, speicher die Datei und guck dir die Veränderung an! +Add that to your CSS, save the file and see how it works! ![Abbildung 14.3](images/margin2.png) Vielleicht können wir auch die Schrift in unserem HTML-Kopf anpassen? Füge dies zu `` in `blog/templates/blog/post_list.html` hinzu: -```html - +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + ``` -Diese Zeile importiert die Schriftart *Lobster* von 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). + +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: -Nun füge die Zeile `font-family: 'Lobster';` in die CSS-Datei `blog/static/css/blog.css` ein. Sie gehört in den `h1 a` Deklaration-Block (der Code zwischen den Klammern `{` und `}`) und lade die Seite neu: +{% filename %}blog/static/css/blog.css{% endfilename %} ```css h1 a { - color: #FCA204; + color: #FCA205; font-family: 'Lobster'; } ``` @@ -163,104 +178,69 @@ h1 a { Super! -CSS hat - wie schon gesagt - ein Klassen-Konzept. Das erlaubt dir, Teile des HTML-Codes mit Namen zu versehen und die Stile (Styles) nur auf diese Teile anzuwenden. Die anderen Teile bleiben davon unberührt. Das ist sehr hilfreich, wenn du z.B. zwei div-Container hast, die ganz verschiedene Sachen bewirken sollen, einer für die Kopfzeile, einer für den Inhalt. Sie sollen dann ja nicht gleich aussehen. +Wie oben erwähnt basiert CSS auf dem Konzept von Klassen. Dies erlaubt Dir einen Teil des HTML Codes mit einem Namen zu versehen und nur für diesen Teil einen Stil hinzuzufügen ohne Auswirkungen auf andere Teile des Codes. Dies kann sehr hilfreich sein! Eventuell hast Du zwei divs die etwas vollkommen Verschiedenes auszeichnen (wie einen Seitentitel oder Post Beitrag). Die Klasse hilft dir sie unterschiedlich aussehen zu lassen. Im nächsten Schritt werden wir den HTML-Code einteilen. Füge eine Klasse (class) names `page-header` dem `div` hinzu, der die Kopfzeilen (header) enthalten soll: -```html - -``` -Jetzt fügen wir noch eine Klasse `post` für den Blog-Inhalt (Post) dem `div` hinzu. +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -```html -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

+```html + ``` -Gemäß der Änderungen im HTML erweitern wir unser CSS mit entsprechenden Selektoren. Selektoren, die mit `.` anfangen, beziehen sich auf Klassen im HTML. Wenn du dich weiter mit dem folgenden CSS-Code auseinandersetzen willst, helfen dir die zahlreichen Anleitungen im Internet weiter. Für den Anfang reicht es aus, folgenden Text in deine `blog/static/css/blog.css`-Datei zu kopieren: - -```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; -} +Jetzt fügen wir noch eine Klasse `post` für den Blog-Inhalt (Post) dem `div` hinzu. -.save { - float: right; -} +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -.post-form textarea, .post-form input { - width: 100%; -} +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` -.top-menu, .top-menu:hover, .top-menu:visited { - color: #ffffff; - float: right; - font-size: 26pt; - margin-right: 20px; -} +Gemäß der Änderungen im HTML erweitern wir unser CSS mit entsprechenden Selektoren. Selektoren, die mit `.` anfangen, beziehen sich auf Klassen im HTML. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. Für den Anfang reicht es aus, folgenden Text in deine `blog/static/css/blog.css`-Datei zu kopieren: -.post { - margin-bottom: 70px; -} +{% filename %}blog/static/css/blog.css{% endfilename %} -.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 { 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; } ``` Der HTML-Code, der für die Anzeige der Blogposts verantwortlich ist, soll durch Klassen erweitert werden. Ersetze den folgenden Code: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
+
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
{% endfor %} ``` in `blog/templates/blog/post_list.html` durch diesen: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html
- {% for post in posts %} -
-
- {{ post.published_date }} + {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
- {% endfor %} + {% endfor %}
@@ -269,11 +249,11 @@ in `blog/templates/blog/post_list.html` durch diesen: Speichere die geänderten Dateien und aktualisiere die Webseite. ![Abbildung 14.4](images/final.png) - -Und?! Sieht viel besser aus, oder!? Der verwendete Code ist nicht allzu schwer zu verstehen. Wenn du ihn liest, sollte schon fast alles klar sein. -Ändere ruhig das eine oder andere im CSS und probiere ein paar Sachen aus. Geht etwas kaputt, mach deine Änderungen im Editor rückgängig und starte von vorn. +Juhuu! Sieht super aus, oder? Schau dir den Code an den wir gerade eingefügt haben. Da siehst du wo wir überall Klassen zu den HTML Objekten hinzugefügt haben um sie in CSS zu referenzieren. Wo würdest du eine Änderung machen um das Datum in Türkis anzuzeigen? + +Hab keine Angst, etwas mit dieser CSS Datei herumzuspielen und versuche ein paar Dinge zu ändern. Mit CSS herumzuspielen kann dir helfen zu verstehen was die verschiedenen Dinge genau machen. Mach dir keine Sorgen wenn etwas kaputt geht, du kannst deine Änderungen immer rückgängig machen! -Wir empfehlen den freien Online-Kurs [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web) als Hausaufgabe. So kannst du alles lernen, was du über das Verschönern von Webseiten mit CSS wissen willst. +Wir empfehlen diesen kostenlosen [Codeacademy HTML & CSS Kurs](https://www.codecademy.com/tracks/web). Er wird dir helfen deine Webseiten mit CSS schöner zu gestalten. -Bereit für das nächste Kapitel? :) +Bereit für das nächste Kapitel? :) \ No newline at end of file diff --git a/de/deploy/README.md b/de/deploy/README.md index b383e1d939f..1ee02245419 100644 --- a/de/deploy/README.md +++ b/de/deploy/README.md @@ -2,285 +2,234 @@ > **Hinweis:** Durch das folgende Kapitel muss man sich manchmal durchbeißen. Bleib dran und gib nicht auf; die Website zu veröffentlichen ist ein sehr wichtiger Schritt. Dieses Kapitel ist in der Mitte des Tutorials platziert, damit dir dein Mentor mit dem etwas anspruchsvolleren Vorgang der Veröffentlichung deiner Website helfen kann. Den Rest des Tutorials kannst du dann auch alleine beenden, sollte die Zeit nicht ausreichen. -Bis jetzt lief die Website nur auf deinem Computer, jetzt wollen wir sie veröffentlichen! Auf Englisch sagt man dazu deploy. Deployen bedeutet, dass du deine Anwendung im Internet veröffentlichst, so dass endlich jeder darauf zugreifen kann :). +Bis jetzt war deine Webseite nur auf deinem Computer verfügbar. Jetzt wirst du lernen wie du sie 'deployst'! Deployen bedeutet, dass du deine Anwendung im Internet veröffentlichst, so dass endlich jeder darauf zugreifen kann. :) -Wie du schon gelernt hast, muss eine Webseite auf einem Server liegen. Es sind eine Menge Server-Anbieter im Internet verfügbar. Wir werden einen verwenden, der einen relativ einfachen Veröffentlichungsprozess (deployment process) hat: [PythonAnywhere](http://pythonanywhere.com/). PythonAnywhere ist kostenlos für kleine Anwendungen, die nicht von vielen Besuchern aufgerufen werden. Also erstmal genau das Richtige für dich. +Wie du schon gelernt hast, muss eine Webseite auf einem Server liegen. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. -Als weiteren externen Dienst werden wir [GitHub](http://www.github.com) nutzen, einen "Code Hosting"-Dienst. Es gibt noch andere solcher Dienste, aber die meisten Programmierer haben heute ein Konto bei GitHub, und du gleich auch! - -GitHub wird unsere Basis für die Übertragung unseres Code von und nach PythonAnywhere sein. +Als weiteren externen Dienst werden wir [GitHub](https://www.github.com) nutzen, einen "Code Hosting"-Dienst. Es gibt noch andere solcher Dienste, aber die meisten Programmierer haben heute ein Konto bei GitHub, und du gleich auch! +Diese drei Orte werden für dich wichtig sein. Die Entwicklung und das Testing wirst du auf deinem lokalen Rechner durchführen. Wenn du mit deinen Änderungen zufrieden bist, wirst du eine Kopie deines Programms auf GitHub veröffentlichen. Deine Website wird auf PythonAnywhere gehostet werden. Ändern kannst du sie, indem du eine neue Version deines Codes von GitHub herunter lädst. # Git -Git ist ein "Versionsverwaltungssystem", das von vielen Programmierern benutzt wird. Diese Software kann Änderungen an Dateien über die Zeit verfolgen, so dass du bestimmte Versionen im Nachhinein wieder aufrufen kannst. Ein bisschen wie die "Track Changes" Funktion in Microsoft Word, aber viel leistungsfähiger. - -## Git installieren +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. -> **Hinweis:** Falls du die Installationsschritte bereits durchgeführt hast, kannst du mit dem nächsten Abschnitt fortfahren und anfangen, dein Git-Repository zu erstellen. - -{% include "/code_editor/instructions.md" %} +{% include "/deploy/install_git.md" %} ## Unser Git-Repository -Git verwaltet die Veränderungen an einer Sammlung von Dateien in einem sogenannten Repository (oder kurz "Repo"). Wir legen eins für unser Projekt an. Öffne deine Konsole und gibt folgende Kommandos im `djangogirls`-Verzeichnis ein: - -> **Hinweis:** Überprüfe dein aktuelles Arbeitsverzeichnis mit dem Befehl `pwd` (OSX/Linux) oder `cd` (Windows) bevor du das Repository initialisierst. Du musst dich im `djangogirls`-Verzeichnis befinden, bevor du fortfährst. +Git verwaltet die Veränderungen an einer Sammlung von Dateien in einem sogenannten Repository (oder kurz "Repo"). Legen wir eines für unser Projekt an. Öffne deine Konsole und gibt folgende Kommandos im `djangogirls`-Verzeichnis ein: -``` -$ git init -Initialized empty Git repository in ~/djangogirls/.git/ -$ git config --global user.name "Dein Name" -$ git config --global user.email du@beispiel.com -``` +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. Du musst dich im `djangogirls`-Verzeichnis befinden, bevor du fortfährst. -Die Initialisierung eines Git-Repository müssen wir nur einmal pro Projekt machen (und du musst nicht noch einmal Deinen Benutzernamen und E-Mail-Adresse eingeben). +{% filename %}command-line{% endfilename %} -Git wird die Änderungen an all den Dateien und Ordnern in diesem Verzeichnis aufzeichnen. Wir wollen aber, dass einige Dateien ignoriert werden. Dazu legen wir eine Datei `.gitignore` im Basisverzeichnis des Repos an. Öffne deinen Editor und erstelle eine neue Datei mit dem folgenden Inhalt: + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Dein Name" + $ git config --global user.email du@beispiel.com + -``` -*.pyc -__pycache__ -myvenv -db.sqlite3 -.DS_Store -``` +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). -Speichere die Datei mit dem Namen `.gitignore` im "djangogirls"-Verzeichnis. +Git wird die Änderungen an all den Dateien und Ordnern in diesem Verzeichnis aufzeichnen. Wir wollen aber, dass einige Dateien ignoriert werden. Dazu legen wir eine Datei `.gitignore` im Basisverzeichnis des Repos an. Öffne deinen Editor und erstelle eine neue Datei mit dem folgenden Inhalt: -> **Hinweis:** Der Punkt vor dem Dateinamen ist wichtig! Wenn du Schwierigkeiten beim Erstellen hast (z.B. lassen Macs im Finder keine Dateien mit Punkt am Anfang erzeugen, Punkt-Dateien sind auf Linux und OS X "versteckte Dateien"), dann verwende die "Speichern unter"-Funktion im Editor, das sollte immer funktionieren. +{% filename %}.gitignore{% endfilename %} -Es ist hilfreich den Befehl `git status` vor `git add` auszuführen oder immer dann, wenn du dir unsicher bist, was geändert wurde. Das schützt vor manchen Überraschungen, wie z. B. das falsche Hinzufügen oder Übertragen von Dateien. Das `git status`-Kommando gibt Informationen über unbeobachtete/veränderte/hinzugefügte Dateien, den Verzweigungsstatus und einiges mehr wieder. Die Ausgabe sollte so oder so ähnlich sein: + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + -``` -$ git status -On branch master +And save it as `.gitignore` in the "djangogirls" folder. -Initial commit +> **Hinweis:** Der Punkt vor dem Dateinamen ist wichtig! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. -Untracked files: - (use "git add ..." to include in what will be committed) +Es ist hilfreich den Befehl `git status` vor `git add` auszuführen oder immer dann, wenn du dir unsicher bist, was geändert wurde. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. Deine Ausgabe sollte dem hier ähneln: - .gitignore - blog/ - manage.py - mysite/ +{% filename %}command-line{% endfilename %} -nothing added to commit but untracked files present (use "git add" to track) -``` + $ 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) + Nun speichern wir unsere Änderungen durch folgende Eingabe in der Konsole: -``` -$ git add -A . -$ git commit -m "Meine Django Girls App, erster Commit" - [...] - 13 files changed, 200 insertions(+) - create mode 100644 .gitignore - [...] - create mode 100644 mysite/wsgi.py -``` - -## Den Code auf GitHub veröffentlichen - -Öffne [GitHub.com](https://www.github.com) und registriere dich für ein neues, kostenloses Benutzerkonto. (Wenn du das bereits in deiner Vorbereitung auf den Workshop getan hast, dann ist das großartig!) +{% filename %}command-line{% endfilename %} -Erstelle dann ein neues Repository und gib ihm den Namen "my-first-blog". Lass das Kontrollkästchen "initialise with a README" deaktiviert, die Einstellung der Option .gitignore frei (das haben wir schon von Hand gemacht) und lass die Lizenz auf "None". - -![](images/new_github_repo.png) - - -> **Achtung:** Der Name `my-first-blog` ist wichtig -- du kannst auch einen anderen wählen, aber er wird im Folgenden noch sehr oft vorkommen und du wirst immer daran denken müssen, ihn in den Anweisungen entsprechend anzupassen. Lass es besser erst mal bei `my-first-blog`. - -Auf der nächsten Seite wird dir die Clone-URL des Repos angezeigt. Nimm die HTTPS-Variante, kopiere sie und füge sie in der Konsole ein: - -![](images/github_get_repo_url_screenshot.png) - -Nun müssen wir das Git-Repository auf deinem Computer mit dem auf GitHub verbinden. - -Gib Folgendes in deine Konsole ein (Ersetze dabei `` durch deinen Benutzernamen, den du bei der Erstellung deines GitHub-Kontos benutzt hast, aber ohne die eckigen Klammern.): - -``` -$ git remote add origin https://github.com//my-first-blog.git -$ git push -u origin master -``` - -Gibt deinen GitHub-Benutzernamen und dein Passwort ein und du solltest etwas Ähnliches wie das hier sehen: - -``` -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. -``` + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + - +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master -Dein Code ist jetzt auf GitHub. Schau gleich mal nach! Dort ist dein Code du in guter Gesellschaft - [Django](https://github.com/django/django), das [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial) und viele andere großartige Open Source Software-Projekte haben ihren Code auf GitHub :) +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + -# Deinen Blog auf PythonAnywhere einrichten +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 -> **Hinweis:** Es ist möglich, dass du bereits ein PythonAnywhere Konto angelegt hast. Wenn ja, dann brauchst du das nicht noch einmal zu tun. +- [new branch] master -> master Branch master set up to track remote branch master from origin. -{% include "/deploy/signup_pythonanywhere.md" %} +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Schau gleich mal nach! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Lass uns den Code von GitHub auf PythonAnywhere übertragen, indem wir einen "Klon" unseres Repositorys erzeugen. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + -## Den Code nach PythonAnywhere übertragen +$ git clone https://github.com//my-first-blog.git -Sobald du dich für PythonAnywhere angemeldet hast, wirst du zu deinem Dashboard bzw. deiner "Konsole" weitergeleitet. Wähle die Option zum Starten einer "Bash", das ist die PythonAnywhere-Version einer Konsole, genau wie die auf deinem Computer. +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + -> **Hinweis:** PythonAnywhere basiert auf Linux. Wenn du Windows benutzt, dann sieht die Konsole etwas anders aus als die Konsole auf deinem Computer. +$ 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 -Lass uns den Code von GitHub auf PythonAnywhere übertragen, indem wir einen "Klon" unseres Repositorys erzeugen. Tippe das Folgende in die Konsole auf PythonAnywhere (vergiss nicht deinen GitHub-Benutzernamen an Stelle von `` zu benutzen): +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + -``` -$ git clone https://github.com//my-first-blog.git -``` - -Dies wird eine Kopie deines Codes auf PythonAnywhere übertragen. Überprüfe es, indem du eingibst `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 -``` - -### Erstelle ein virtualenv auf PythonAnywhere - -Genauso wie du auf deinem eigenen Computer ein virtualenv erstellt hast, kannst du auch eins auf PythonAnywhere erstellen. Schreibe Folgendes in die Bash: - -``` $ cd my-first-blog -$ virtualenv --python=python3.5 myvenv -Running virtualenv with interpreter /usr/bin/python3.5 -[...] -Installing setuptools, pip...done. +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. $ source myvenv/bin/activate -(myvenv) $ pip install django~=1.10.0 -Collecting django -[...] -Successfully installed django-1.10.4 -``` - -> **Hinweis:** Der Schritt `pip install` kann ein paar Minuten dauern. Hab etwas Geduld! Aber, wenn es länger als 5 Minuten dauern sollte, dann ist etwas falsch gelaufen. Frag am besten deinen Coach. +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 - - - - -### Erstellen einer Datenbank auf PythonAnywhere - -Hier ist ein weiterer Unterschied zwischen deinem Computer und einem Server: unterschiedliche Datenbanken werden benutzt. Dadurch können sich Benutzerkonten und Posts auf dem Server und auf deinem Computer unterscheiden. - -Wir initialisieren die Datenbank auf dem Server genauso, wie wir es auf deinen Computer mit `migrate` und `createsuperuser` gemacht haben: - -``` -(mvenv) $ python manage.py migrate -Operations to perform: -[...] - Applying sessions.0001_initial... OK - - -(mvenv) $ python manage.py createsuperuser -``` - -## Veröffentlichen unseres Blogs als Web-App - -Jetzt ist unser Code auf PythonAnywhere, unser virtualenv ist bereit, die statischen Dateien sind gesammelt und die Datenbank ist initialisiert. Wir sind bereit es als Web-App zu veröffentlichen! - -Gehe zurück zum PythonAnywhere Dashboard, indem du auf das Logo klickst und klicke anschließend auf den **Web** Menüpunkt. Dort wählst du **Add a new web app** aus. - -Nach der Bestätigung deines Domainnamens wählst du **manual configuration** (NB *nicht* die "Django"-Option) im Dialogfeld aus. Entscheide dich als Nächstes für **Python 3.4** und klicke "Next", um den Assistenten zu beenden. - -> **Hinweis:** Versichere dich, dass du die Option "Manual configuration" ausgewählt hast und nicht "Django". Wir sind einfach zu cool für das Standard PythonAnywhere Django Setup :-) - -### Angeben des Virtualenv - -Du wirst auf den PythonAnywhere-Konfigurationsschirm für deine Web-App weitergeleitet. Dorthin musst du immer gehen, wenn du Änderungen an deiner App auf dem Server vornehmen willst. - -![](images/pythonanywhere_web_tab_virtualenv.png) - -In der "Virtualenv"-Sektion, klicke auf den roten Text, welcher sagt: "Enter the path to a virtualenv" und gieb ein: `/home//my-first-blog/myvenv/`. Klicke auf die blaue Box mit dem Häkchen, um den Pfad zu speichern, bevor es weitergeht. - -> **Hinweis:** Ersetze deinen eigenen Benutzernamen soweit erforderlich. Falls du einen Fehler machst, wird dir PythonAnywhere eine kleine Warnung anzeigen. - -### Konfigurieren der WSGI-Datei - -Django funktioniert durch Verwendung des "WSGI Protokolls", ein Standard für Python-Webseiten, der von PythonAnywhere unterstützt wird. Um PythonAnywhere so zu konfigurieren, dass es unseren Django-Blog erkennt, editieren wir eine WSGI-Konfigurationsdatei. - -Klicke auf den "WSGI configuration file"-Link (in der "Code"-Sektion im oberen Teil der Seite -- es sollte ungefähr so benannt sein `/var/www/_pythonanywhere_com_wsgi.py`) und du wirst zu einem Editor geführt. - -Lösche alle Inhalte und ersetze sie durch: - -```python -import os -import sys - -path = os.path.expanduser('~/my-first-blog') -if path not in sys.path: - sys.path.append(path) -os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser -from django.core.wsgi import get_wsgi_application -from django.contrib.staticfiles.handlers import StaticFilesHandler -application = StaticFilesHandler(get_wsgi_application()) -``` +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + -> **Hinweis:** Vergiss nicht deinen Benutzernamen an der Stelle `` einzusetzen +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. -Die Aufgabe dieser Datei ist es, PythonAnywhere zu sagen, wo unsere Web-App lebt und wie der Django Einstellungsdateiname ist. Es richtet außerdem das "whitenoise" Werkzeug für statische Dateien ein. +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. Wir werden später im Tutorial ein wenig mehr über statische Dateien erfahren, wenn wir das CSS für unsere Seite bearbeiten. Klicke auf **Save** und gehe dann zu dem **Web**-Tab zurück. @@ -290,21 +239,22 @@ Wir sind fertig! Drücke auf den großen, grünen **Reload**-Knopf und du kannst Falls du beim Versuch deine Seite zu besuchen, einen Fehler siehst, ist der erste Ort, an dem man nach Debugging-Infos schauen sollte, dein **error log**. Einen Link dazu findest du auf dem PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). Schau nach, ob Fehlermeldungen enthalten sind; die neuesten findest du unten. Häufige Probleme sind: -* Einen der Schritte vergessen, die wir in der Konsole erledigt haben: das virtualenv kreieren, es aktivieren, Django darin installieren, collectstatic auszuführen, die Datenbank zu migrieren. +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. -* Einen Fehler in dem virutalenv-Pfad auf dem Web-Tab machen -- falls es ein Problem gibt, wird dann dort normalerweise eine kleine rote Fehlermeldung erscheinen. +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. -* Einen Fehler in der WSGI-Konfigurationsdatei machen -- ist der Pfad zu deinem my-first-blog Ordner richtig? +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? -* Hast du die selbe Pythonversion für dein virtualenv gewählt wie für deine Web-App? Beide sollten 3.4 sein. +- Hast du die selbe Pythonversion für dein virtualenv gewählt wie für deine Web-App? Beide sollten 3.6 sein. -* Es gibt einige [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). Und denk dran, dein Coach ist da, um dir zu helfen! - # Du bist live! -Die Standardseite für deine Site sollte "Welcome to Django" anzeigen, genauso wie auf deinem lokalen Computer. Versuch `/admin/` am Ende der URL hinzuzufügen und du gelangst zur Adminseite. Melde dich mit deinen Benutzernamen und Passwort an. Wie du siehst, kannst du neue Posts auf dem Server hinzufügen. +The default page for your site should say "It worked!", just like it does on your local computer. Versuch `/admin/` am Ende der URL hinzuzufügen und du gelangst zur Adminseite. Melde dich mit deinen Benutzernamen und Passwort an. Wie du siehst, kannst du neue Posts auf dem Server hinzufügen. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Ziemlich cool, oder? -Klopf dir *kräftig* auf die Schulter! Das Deployment ist eines der kompliziertesten Dinge der Web-Entwicklung und es dauert oftmals mehrere Tage, bis alles läuft. Aber du hast deine Site jetzt live, im echten Internet, einfach so! +Klopf dir *kräftig* auf die Schulter! Das Deployment ist eines der kompliziertesten Dinge der Web-Entwicklung und es dauert oftmals mehrere Tage, bis alles läuft. Aber du hast deine Site jetzt live, im echten Internet, einfach so! \ No newline at end of file diff --git a/de/deploy/install_git.md b/de/deploy/install_git.md index 3d8a8d77b4c..2203830d774 100644 --- a/de/deploy/install_git.md +++ b/de/deploy/install_git.md @@ -1,19 +1,52 @@ -### Windows +Git ist ein "Versionsverwaltungssystem", das von vielen Programmierern benutzt wird. Diese Software kann Änderungen an Dateien über die Zeit verfolgen, so dass du bestimmte Versionen im Nachhinein wieder aufrufen kannst. Ein bisschen wie die "Track Changes" Funktion in Microsoft Word, aber viel leistungsfähiger. -Du kannst Git von [git-scm.com](http://git-scm.com/) herunterladen. Du kannst immer "weiter" klicken - "next next next" - an allen bis auf einer Stelle; im 5. Schritt "Adjusting your PATH environment", nimm "Run Git and associated Unix tools from the Windows command-line" (die letzte Option). Die anderen Voreinstellungen sind ok. "Checkout"-Stil "Windows" und "Commit" mit "Unix line endings" (Zeilenende im Unix-Format) sind die richtigen Einstellungen. +## Git installieren -### OS X (Mac) + -Git von [git-scm.com](http://git-scm.com/) herunterladen und dann den Anweisungen folgen. +Du kannst Git von [git-scm.com](https://git-scm.com/) herunterladen. You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Die anderen Voreinstellungen sind ok. "Checkout"-Stil "Windows" und "Commit" mit "Unix line endings" (Zeilenende im Unix-Format) sind die richtigen Einstellungen. -### Linux +Do not forget to restart the command prompt or powershell after the installation finished successfully. -Falls es noch nicht installiert sein sollte, sollte git als Paket im Paketmanager enthalten sein. Versuche je nach Distribution: + + +Git von [git-scm.com](https://git-scm.com/) herunterladen und dann den Anweisungen folgen. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} ```bash -sudo apt-get install git +$ sudo dnf install git ``` - # oder + + + + + +{% filename %}command-line{% endfilename %} + ```bash -sudo yum install git +$ sudo zypper install git ``` + + \ No newline at end of file diff --git a/de/deploy/signup_pythonanywhere.md b/de/deploy/signup_pythonanywhere.md index aada52a2cbf..ca66bd0de69 100644 --- a/de/deploy/signup_pythonanywhere.md +++ b/de/deploy/signup_pythonanywhere.md @@ -1,5 +1,5 @@ -Als Nächstes erstellst du ein kostenfreies "Beginner"-Konto auf PythonAnywhere. +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. - * [www.pythonanywhere.com](https://www.pythonanywhere.com/) +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) -> **Beachte:** Wenn du dort deinen Benutzernamen aussuchst, dann denke daran, dass sich die URL zu deinem Blog folgendermaßen zusammensetzt: `deinbenutzername.pythonanywhere.com`. Wähle demnach deinen eigenen Nicknamen oder einen Namen, der deinen Blog umschreibt. \ No newline at end of file +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/de/django/README.md b/de/django/README.md index 80be5ea27f6..563c745bffa 100644 --- a/de/django/README.md +++ b/de/django/README.md @@ -1,26 +1,26 @@ # Django - Was ist das? -Django (*/ˈdʒæŋɡoʊ/ jang-goh*) ist ein freies, Open-Source Web-Anwendungs-Framework, geschrieben in Python. Ein Web-(Anwendungs-)Framework ist eine Art Baukastensystem, das dir mit vielen vorgefertigten Teilen die Entwicklung von Webseiten stark erleichtert. +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. Ein Web-(Anwendungs-)Framework ist eine Art Baukastensystem, das dir mit vielen vorgefertigten Teilen die Entwicklung von Webseiten stark erleichtert. Wenn du eine Website entwickelst, brauchst du immer wieder sehr ähnliche Elemente: Einen Weg Benutzer zu verwalten (Registrierung, Anmeldung, Abmeldung etc.), einen Administrationsbereich, Formulare, Upload von Dateien usw. -Glücklicherweise wurde schon vor einiger Zeit erkannt, dass Web-Entwickler diese Probleme immer wieder zu lösen hatten und haben. Gemeinsam entstanden so verschiedene Frameworks (Django ist so eines), die die Web-Entwicklung durch vorgefertigte Elemente erleichtern. +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. -Frameworks sind da, damit du das Rad nicht neu erfinden musst. Du kannst dich auf die konkret zu erfüllenden Anforderungen der Webseite kümmern. Die grundlegende Basis der Webseite stellt dir das Framework zur Verfügung. +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. ## Warum brauchst du ein Framework? -Um besser zu verstehen, welchen Vorteil dir Django bietet, werfen wir einen Blick auf Server im Allgemeinen. Als Erstes muss der Server wissen, dass er eine Webseite ausliefern soll. +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. -Der Server hat mehrere "Ports", vergleichbar einem Briefkasten, der auf eingehende Briefe "Anfragen"/"requests" überwacht wird. Das macht der Webserver. Der Webserver liest die eingeworfenen Briefe (requests) und beantwortet sie mit der Webseite (response). Um etwas ausliefern zu können, brauchen wir Inhalte. Und Django hilft dir dabei, diese Inhalte zu erstellen. +Der Server hat mehrere "Ports", vergleichbar einem Briefkasten, der auf eingehende Briefe "Anfragen"/"requests" überwacht wird. Das macht der Webserver. The web server reads the letter and then sends a response with a webpage. Um etwas ausliefern zu können, brauchen wir Inhalte. Und Django hilft dir dabei, diese Inhalte zu erstellen. ## Was passiert, wenn jemand eine Webseite beim Server anfordert? -Wenn der request beim Web-Server ankommt, reicht dieser die Anfrage an Django weiter. Und Django versucht herauszufinden, welche Seite genau angefordert wurde. Django wertet zuerst die Adresse der Webseite aus und versucht herauszufinden, was geliefert werden soll. Dafür ist der **urlresolver** von Django verantwortlich. URL - Uniform Resource Locator ist ein anderer Name für die Web-Adresse, daher der Name *urlresolver*. Sehr schlau ist er aber nicht. Er hat eine Musterliste und vergleicht diese mit der URL. Der Vergleich der Muster erfolgt von oben nach unten. Wenn ein Muster auf die URL zutrifft, wird der damit verknüpften Funktion (der sogenannten *view*) der request/die Anfrage übergeben). +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). Stell dir eine Postbotin mit einem Brief vor. Sie geht die Straße entlang und prüft jede Hausnummer mit der Adresse auf dem Brief. Wenn beide passen, dann steckt sie den Brief in den Briefkasten. So funktioniert der urlresolver! -In der *view* Funktion passieren all die interessanten Dinge: wir können in eine Datenbank gucken und dort nach Informationen suchen. Vielleicht wollte die Benutzerin irgendetwas in den Daten ändern? So, als ob der Brief sagen würde: "Bitte ändere meine Stellenbeschreibung!" Die Funktion *view* kann nun prüfen, ob du dazu berechtigt bist, im positiven Fall die Änderungen durchführen und im Anschluss eine Nachricht zurücksenden. Die *view* erzeugt eine Antwort und Django sendet diese an den Browser zurück, wo sie dargestellt wird. +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Vielleicht wollte die Benutzerin irgendetwas in den Daten ändern? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. Natürlich, ist die Beschreibung oben ein wenig vereinfacht, aber du musst noch nicht all die technischen Details wissen. Eine generelle Vorstellung zu haben, reicht erstmal. diff --git a/de/django_admin/README.md b/de/django_admin/README.md index cec1f84a41f..35f18a49f5a 100644 --- a/de/django_admin/README.md +++ b/de/django_admin/README.md @@ -1,8 +1,10 @@ # Django Administration -Zum Hinzufügen, Bearbeiten und Löschen von Blogposts benutzen wir den Django Admin, das eingebaute Administrations-Backend von Django. +To add, edit and delete the posts we've just modeled, we will use Django admin. -Öffne die Datei `blog/admin.py` und ersetze den Inhalt wie folgt: +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} ```python from django.contrib import admin @@ -13,31 +15,43 @@ admin.site.register(Post) Wie du siehst, importieren wir hier das Model "Post", das wir im vorigen Kapitel erstellt haben. Damit unser Model auf der Admin-Seite sichtbar wird, müssen wir es mit `admin.site.register(Post)` registrieren. -Okay, wir sehen uns nun unser Post-Model an. Denk daran, `python manage.py runserver` in die Konsole einzugeben, um den Webserver zu starten. Öffne dann deinen Browser und gib die Adresse http://127.0.0.1:8000/admin/ ein. Du solltest nun eine Login-Seite wie diese sehen: +Okay, wir sehen uns nun unser Post-Model an. Denk daran, `python manage.py runserver` in die Konsole einzugeben, um den Webserver zu starten. Go to your browser and type the address http://127.0.0.1:8000/admin/. Du siehst eine Anmeldeseite: ![Login Seite](images/login_page2.png) -Um dich einzuloggen, musst du einen *superuser* erzeugen - einen Benutzer, welcher Kontrolle über alles auf der Site hat. Geh zurück zu der Kommandozeile und tippe `python manage.py createsuperuser`, und drücke Enter. Wenn gefordert, gibst du deinen Benutzernamen (Kleinbuchstaben, keine Leerzeichen), E-Mail-Adresse und Passwort ein. Keine Sorge, dass du das Passwort nicht siehst, das du gerade eingibst - das soll so sein. Tipp es einfach ein und drücke `Enter` um fortzufahren. Du solltest nun Folgendes sehen (wobei Username und Email deine sein sollten): +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. -``` -(myvenv) ~/djangogirls$ python manage.py createsuperuser -Username: admin -Email address: admin@admin.com -Password: -Password (again): -Superuser created successfully. -``` +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + -Geh nochmal in deinen Browser und log dich mit den Daten des Superusers ein, den du gerade erstellt hast. Du solltest nun das Django Admin Dashboard sehen. +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. -![Django Administration](images/django_admin3.png) +![Django admin](images/django_admin3.png) -Gehe zu Posts und experimentiere ein wenig damit. Füge 5 oder 6 Blogposts hinzu. Mach dir keine Sorgen wegen des Inhalts - du kannst einfach etwas Text aus diesem Tutorial kopieren und einfügen, um Zeit zu sparen :-). +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) -Achte darauf, dass bei wenigstens zwei oder drei Posts (aber nicht bei allen) das Veröffentlichungsdatum (publish date) eingetragen ist. Das werden wir später noch brauchen. +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. -![Django Administration](images/edit_post3.png) +![Django admin](images/edit_post3.png) -Wenn du mehr über Django Admin wissen willst, solltest du dir die Django Dokumentation ansehen: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ -Jetzt ist wahrscheinlich ein guter Moment, um dir einen Kaffee (oder Tee) zu gönnen und neue Kraft tanken. Du hast dein erstes Django-Model erstellt - du hast dir eine kleine Pause verdient! +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/de/django_forms/README.md b/de/django_forms/README.md index cf60e48fed2..0f61c473cc2 100644 --- a/de/django_forms/README.md +++ b/de/django_forms/README.md @@ -1,6 +1,6 @@ # Django Formulare -Als Letztes möchten wir auf unserer Website noch die Möglichkeit haben, Blogposts hinzuzufügen und zu editieren. Die Django `admin`-Oberfläche ist cool, aber eher schwierig anzupassen und hübsch zu machen. Mit Formularen, `forms` , haben wir die absolute Kontrolle über unser Interface, wir können fast alles machen, was man sich vorstellen kann! +Als Letztes möchten wir auf unserer Website noch die Möglichkeit haben, Blogposts hinzuzufügen und zu editieren. Die Django `admin`-Oberfläche ist cool, aber eher schwierig anzupassen und hübsch zu machen. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! Das Gute an Django Forms ist, dass man sie entweder vollständig selbst definieren oder eine `ModelForm` erstellen kann, welche den Inhalt des Formulars in das Model speichert. @@ -10,12 +10,13 @@ So wie die anderen wichtigen Django-Komponenten haben auch die Forms ihre eigene Wir erstellen nun eine Datei mit diesem Namen im `blog` Verzeichnis. -``` -blog - └── forms.py -``` + blog + └── forms.py + -So, jetzt lass uns diese öffnen und folgenden Code hinzufügen: +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} ```python from django import forms @@ -25,33 +26,37 @@ from .models import Post class PostForm(forms.ModelForm): class Meta: - model = Post - fields = ('title', 'text',) + model = Post + fields = ('title', 'text',) ``` Zuerst müssen wir die Django Forms importieren (`from django import forms`) und natürlich auch unser `Post` Model (`from .models import Post`). -Wie du wahrscheinlich schon vermutet hast, `PostForm` ist der Name unseres Formulars. Wir müssen Django mitteilen, dass unser Formular ein `ModelForm` ist (so kann Django ein bisschen für uns zaubern) - `forms.ModelForm` ist dafür verantwortlich. +Wie du wahrscheinlich schon vermutet hast, `PostForm` ist der Name unseres Formulars. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. Als Nächstes sehen wir uns `class Meta` an, damit sagen wir Django, welches Model benutzt werden soll, um das Formular zu erstellen (`model = Post`). -Nun können wir bestimmen, welche(s) Feld(er) unser Formular besitzen soll. Wir wollen hier nur den `title` und `text` sichtbar machen - der `author` sollte die Person sein, die gerade eingeloggt ist (Du!) und `created_date` sollte automatisch generiert werden, wenn der Post erstellt wird (also im Code). Stimmt's? +Nun können wir bestimmen, welche(s) Feld(er) unser Formular besitzen soll. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? Und das war's schon! Jetzt müssen wir das Formular nur noch in einem *view* benutzen und im Template darstellen. -Also erstellen wir hier auch wieder einen Link auf die Seite, eine URL, einen View und ein Template. +So once again we will create a link to the page, a URL, a view and a template. ## Link auf eine Seite mit dem Formular Jetzt ist es an der Zeit, `blog/templates/blog/base.html` zu öffnen. Wir fügen einen Link in `div` hinzu mit dem Namen `page-header`: +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html ``` -Merk dir, dass wir unseren neuen View `post_new` nennen wollen. +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. -Nach Hinzufügen der Zeile sieht deine HTML-Datei so aus: +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% load staticfiles %} @@ -86,12 +91,16 @@ Nach dem Speichern und Neuladen von http://127.0.0.1:8000 siehst du den bekannte Wir öffnen `blog/urls.py` und fügen eine Zeile hinzu: +{% filename %}blog/urls.py{% endfilename %} + ```python url(r'^post/new/$', views.post_new, name='post_new'), ``` Der finale Code sieht dann so aus: +{% filename %}blog/urls.py{% endfilename %} + ```python from django.conf.urls import url from . import views @@ -103,17 +112,21 @@ urlpatterns = [ ] ``` -Nach dem Neuladen der Seite sehen wir einen `AttributeError`, weil wir noch keinen `post_new` View erstellt haben. Fügen wir ihn gleich hinzu! +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. ## Der post_new View Jetzt wird es Zeit, die `blog/views.py` Datei zu öffnen und die folgenden Zeilen zu den anderen `from` Zeilen hinzuzufügen: +{% filename %}blog/views.py{% endfilename %} + ```python from .forms import PostForm ``` -und unseren *view*: +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): @@ -121,20 +134,22 @@ def post_new(request): return render(request, 'blog/post_edit.html', {'form': form}) ``` -Um ein neues `PostForm` zu erstellen, rufen wir die `PostForm()` Methode auf und übergeben sie an das Template. Wir kommen gleich nochmal zu dem *view* zurück, aber jetzt erstellen wir schnell ein Template für das Form. +Um ein neues `PostForm` zu erstellen, rufen wir die `PostForm()` Methode auf und übergeben sie an das Template. We will go back to this *view*, but for now, let's quickly create a template for the form. ## Template Wir müssen eine Datei `post_edit.html` im Verzeichnis `blog/templates/blog` erstellen. Damit ein Formular funktioniert, benötigen wir einige Dinge: -* Wir müssen das Formular anzeigen. Wir können das, zum Beispiel, mit einem simplen `{% raw %}{{ form.as_p }}{% endraw %}` tun. -* Die Zeile oben muss von einem HTML-Formular-Tag eingeschlossen werden `...`. -* Wir benötigen einen `Save`-Button. Wir erstellen diesen mit einem HTML-Button: ``. -* Und schließlich fügen wir nach dem öffnenden `
` Tag `{% raw %}{% csrf_token %}{% endraw %}` hinzu. Das ist sehr wichtig, da es deine Formulare sicher macht! Django wird sich beschweren, wenn du dies vergisst und trotzdem versuchst, das Formular zu speichern: +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...
`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. Das ist sehr wichtig, da es deine Formulare sicher macht! If you forget about this bit, Django will complain when you try to save the form: ![CSFR Forbidden page](images/csrf2.png) -Ok, also schauen wir mal, wie der HTML-Code in `post_edit.html` aussehen sollte: +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -152,15 +167,17 @@ So, jetzt aktualisieren wir die Seite! Yay! Das Formular wird angezeigt! ![Neues Formular](images/new_form2.png) -Aber Moment! Wenn du irgendetwas eintippst in das `title`- oder `text`-Feld und versuchst zu speichern - was wird wohl passieren? +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? -Nichts! Wir landen wieder auf der selben Seite und unser Text ist verschwunden... und kein neuer Post wurde hinzugefügt. Was lief denn hier schief? +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? Die Antwort ist: nichts. Wir müssen einfach noch etwas mehr Arbeit in unseren *view* stecken. ## Speichern des Formulars -Öffne `blog/views.py` erneut. Derzeit ist alles, was wir in dem View `post_new` haben, das hier: +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): @@ -168,9 +185,11 @@ def post_new(request): return render(request, 'blog/post_edit.html', {'form': form}) ``` -Wenn wir das Formular übermitteln, werden wir zur selben Ansicht weitergeleitet, aber dieses Mal haben wir mehr Daten in `request`, genauer in `request.POST` (der Name hat nichts zu tun mit einem "Blogpost", sondern damit dass wir Daten "posten"). Erinnerst du dich daran, dass in der HTML-Datei unsere `` Definition die Variable `method="POST"` hatte? Alle Felder aus dem Formular sind jetzt in `request.POST`. Du solltest `POST` nicht umbenennen (der einzige andere gültige Wert für `method` ist `GET`, wir wollen hier jetzt aber nicht auf den Unterschied eingehen). +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `` definition had the variable `method="POST"`? Alle Felder aus dem Formular sind jetzt in `request.POST`. Du solltest `POST` nicht umbenennen (der einzige andere gültige Wert für `method` ist `GET`, wir wollen hier jetzt aber nicht auf den Unterschied eingehen). -Wir haben also in unserem *view* zwei separate Situationen zu bearbeiten. Erstens: Wenn wir zum ersten Mal auf die Seite zugreifen und wir ein leeres Formular haben wollen. Zweitens: Wenn wir zurück zu der *view* gehen, mit all den Formulardaten, die wir gerade eingegeben haben. Wir müssen also eine Bedingung hinzufügen (dafür verwenden wir `if`). +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. Wir müssen also eine Bedingung hinzufügen (dafür verwenden wir `if`): + +{% filename %}blog/views.py{% endfilename %} ```python if request.method == "POST": @@ -179,16 +198,20 @@ else: form = PostForm() ``` -Jetzt ist es an der Zeit, die Punkte `[...]` auszufüllen. Wenn `method` `POST` ist, dann wollen wir die `PostForm` mit den Daten aus dem Formular konstruieren, richtig? Wir tun das mit: +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} ```python form = PostForm(request.POST) ``` -Super einfach! Als Nächstes müssen wir testen, ob das Formular korrekt ist (alle benötigten Felder sind ausgefüllt, keine inkorrekten Werte werden gespeichert). Wir tun das mit `form.is_valid()`. +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. Wir überprüfen also, ob das Formular gültig ist und wenn ja, können wir es speichern! +{% filename %}blog/views.py{% endfilename %} + ```python if form.is_valid(): post = form.save(commit=False) @@ -197,23 +220,29 @@ if form.is_valid(): post.save() ``` -Im Grunde passieren hier zwei Dinge: Wir speichern das Formular mit `form.save` und wir fügen einen Autor hinzu (da es bislang kein `author` Feld in der `PostForm` gab und dieses Feld notwendig ist!). `commit=False` bedeutet, dass wir das `Post` Model noch nicht speichern wollen - wir wollen erst noch den Autor hinzufügen. Meistens wirst du `form.save()` ohne `commit=False` benutzen, aber in diesem Fall müssen wir es so tun. `post.save()` wird die Änderungen sichern (den Autor hinzufügen) und ein neuer Blogpost ist kreiert! +Im Grunde passieren hier zwei Dinge: Wir speichern das Formular mit `form.save` und wir fügen einen Autor hinzu (da es bislang kein `author` Feld in der `PostForm` gab und dieses Feld notwendig ist). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! -Nun wäre es noch genial, wenn wir direkt zu der `post_detail` Seite unseres neu erstellten Blogposts gehen könnten, richtig? Um dies zu tun, benötigen wir einen weiteren Import: +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import redirect -``` +``` -Füge dies direkt am Anfang der Datei hinzu. Jetzt können wir endlich sagen: Gehe zu der `post_detail` Seite für unsere neu erstellten Posts. +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} ```python return redirect('post_detail', pk=post.pk) ``` -`blog.views.post_detail` ist der Name unseres Views, zu dem wir springen wollen. Erinnerst du dich, dass dieser *view* einen `pk` benötigt? Um diesen an den View weiterzugeben, benutzen wir `pk=post.pk`, wobei `post` unser neu erstellter Blogpost ist! +`post_detail` is the name of the view we want to go to. Erinnerst du dich, dass dieser *view* einen `pk` benötigt? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? -Ok, wir haben jetzt eine ganze Menge geredet, aber du willst bestimmt sehen, wie die gesamte *view* aussieht, richtig? +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): @@ -230,37 +259,41 @@ def post_new(request): return render(request, 'blog/post_edit.html', {'form': form}) ``` -Schauen wir mal, ob es funktioniert. Gehe zu der Seite http://127.0.0.1:8000/post/new/, füge einen `title` und `text` hinzu und speichere es... und voilà! Der neue Blogpost wird hinzugefügt und wir werden auf die `Post_detail` Seite umgeleitet! +Schauen wir mal, ob es funktioniert. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! -Du hast vielleicht bemerkt, dass wir das Veröffentlichungsdatum festlegen, bevor wir den Post veröffentlichen. Später werden wir einen *publish button* in **Django Girls Tutorial: Extensions** einführen. +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. Das ist genial! -## Formularvalidierung +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. Dies wird das Problem vorübergehend lösen. Es gibt eine permanente Lösung dafür, die im Kapitel **Homework: add security to your website!** nach dem Haupttutorial auf dich wartet. -Jetzt zeigen wir dir, wie cool Django Formulare sind. Ein Blogpost muss `title`- und `text`-Felder besitzen. In unserem `Post`-Model haben wir (im Gegensatz zu dem `published_date`) nicht festgelegt, dass diese Felder nicht benötigt werden, also nimmt Django standardmäßig an, dass sie definiert werden. +![Logged in error](images/post_create_error.png) -Versuch das Formular ohne `title` und `text` zu speichern. Rate, was passieren wird! +## Formularvalidierung -![Formularvalidierung](images/form_validation2.png) +Jetzt zeigen wir dir, wie cool Django Formulare sind. Ein Blogpost muss `title`- und `text`-Felder besitzen. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. -Django kümmert sich darum sicherzustellen, dass alle Felder in unserem Formular richtig sind. Ist das nicht großartig? +Try to save the form without `title` and `text`. Guess what will happen! -> Da wir vor Kurzem das Django Admin Interface benutzt haben, denkt das System, dass wir noch angemeldet sind. Es gibt einige Situationen, welche dazu führen können, dass wir ausgeloggt werden (Schließen des Browsers, Neustarten der Datenbank etc). Wenn du feststellst, dass du bei dem Erstellen von Posts Fehlermeldungen bekommst, die auf nicht angemeldete Nutzer zurückzuführen sind, dann gehe zu der Admin Seite http://127.0.0.1:8000/admin und logge dich erneut ein. Dies wird das Problem vorübergehend lösen. Es gibt eine permanente Lösung dafür, die im Kapitel **Homework: add security to your website!** nach dem Haupttutorial auf dich wartet. +![Formularvalidierung](images/form_validation2.png) -![Logged in error](images/post_create_error.png) +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? ## Formular bearbeiten -Jetzt wissen wir, wie ein neues Formular hinzugefügt wird. Aber was ist, wenn wir ein bereits bestehendes bearbeiten wollen? Das funktioniert so ähnlich wie das, was wir gerade getan haben. Lass uns schnell ein paar wichtige Dinge erstellen (falls du etwas nicht verstehst, solltest du deinen Coach fragen oder in den vorherigen Kapiteln nachschlagen, da wir all die Schritte bereits behandelt haben). +Jetzt wissen wir, wie ein neues Formular hinzugefügt wird. Aber was ist, wenn wir ein bereits bestehendes bearbeiten wollen? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) -Öffne `blog/templates/blog/post_detail.html` und füge diese Zeile hinzu: +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html ``` -damit die Vorlage so aussieht: +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -281,13 +314,17 @@ damit die Vorlage so aussieht: In `blog/urls.py` fügen wir folgende Zeile ein: +{% filename %}blog/urls.py{% endfilename %} + ```python url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), ``` Wir werden die Vorlage `blog/templates/blog/post_edit.html` wiederverwenden, daher ist das einzig Fehlende eine neue *view*. -Öffne `blog/views.py` und füge ganz am Ende der Datei Folgendes hinzu: +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} ```python def post_edit(request, pk): @@ -305,19 +342,23 @@ def post_edit(request, pk): return render(request, 'blog/post_edit.html', {'form': form}) ``` -Sieht genauso aus wie unsere `post_new` view, oder? Aber nicht ganz. Der Unterschied: Wir übergeben einen zusätzlichen `pk` Parameter von den Urls. Und: Wir bekommen das `Post`-Model, welches wir bearbeiten wollen, mit `get_object_or_404(Post, pk=pk)` und wenn wir dann ein Formular erstellen, übergeben wir post als `instance`, wenn wir das Formular speichern: +Sieht genauso aus wie unsere `post_new` view, oder? Aber nicht ganz. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} ```python form = PostForm(request.POST, instance=post) ``` -als auch, wenn wir ein Formular mit post zum Editieren öffnen: +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} ```python form = PostForm(instance=post) ``` -Ok, lass uns mal schauen, ob das funktioniert! Geh auf die `post_detail`-Seite. Dort sollte sich ein Editier-Button in der oberen rechten Ecke befinden: +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: ![Schaltfläche "Bearbeiten"](images/edit_button2.png) @@ -325,23 +366,27 @@ Wenn du darauf klickst, siehst du das Formular mit unserem Blogpost: ![Formular bearbeiten](images/edit_form2.png) -Probier doch einmal den Titel oder den Text zu ändern und die Änderungen zu speichern! +Feel free to change the title or the text and save the changes! Herzlichen Glückwunsch! Deine Anwendung nimmt mehr Gestalt an! -Falls du mehr Informationen über Django Formulare benötigst, solltest du die offizielle Dokumentation lesen: https://docs.djangoproject.com/en/1.8/topics/forms/ +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ ## Sicherheit -Neue Posts mit nur einem Linkklick zu erstellen, ist großartig! Aber im Moment ist jeder, der deine Seite besucht in der Lage, einen neuen Blogpost zu veröffentlichen und das ist etwas, dass du garantiert nicht willst. Lass es uns so einrichten, dass der Button nur für dich sichtbar ist und nicht für jeden. +Neue Posts mit nur einem Linkklick zu erstellen, ist großartig! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Lasst es uns so machen, das der Button für dich angezeigt wird aber für niemanden sonst. Finde in der Datei `blog/templates/blog/base.html` unseren `page-header` `div` und das Anchor-Tag, welches du zuvor eingefügt hast. Es sollte so aussehen: +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html ``` -Wir fügen ein weiteres `{% if %}`-Tag ein, was dafür sorgt, dass der Link nur für angemeldete Nutzer angezeigt wird. Im Moment bist das also nur du! Ändere den ``-Tag zu Folgendem: +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Ändere den ``-Tag zu Folgendem: + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% if user.is_authenticated %} @@ -349,36 +394,54 @@ Wir fügen ein weiteres `{% if %}`-Tag ein, was dafür sorgt, dass der Link nur {% endif %} ``` -Dieses `{% if %}` sorgt dafür, dass der Link nur zu dem Browser geschickt wird, wenn der anfragende Nutzer auch angemeldet ist. Das verhindert das Erzeugen neuer Posts nicht komplett, ist aber ein sehr guter erster Schritt. In der Erweiterungslektion kümmern wir uns ausgiebiger um Sicherheit. - -Da du wahrscheinlich angemeldet bist, wirst du nichts Neues sehen, wenn du die Seite aktualisierst. Lade die Seite in einem neuen Browser oder im Inkognito-Modus und du wirst sehen, dass der Link nicht auftaucht! +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. Das verhindert das Erzeugen neuer Posts nicht komplett, ist aber ein sehr guter erster Schritt. In der Erweiterungslektion kümmern wir uns ausgiebiger um Sicherheit. -## Noch eine Sache: Zeit für das Deployment! +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. -Mal sehen, ob das alles auch auf PythonAnywhere funktioniert. Zeit für ein weiteres Deployment! +Open `blog/templates/blog/post_detail.html` and find this line: -* Checke als Erstes deinen neuen Code ein und lade ihn auf GitHub hoch +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} -``` -$ git status -$ git add --all . -$ git status -$ git commit -m "Added views to create/edit blog post inside the site." -$ git push +```html + ``` -* Dann führe Folgendes in der [PythonAnywhere Bash Konsole](https://www.pythonanywhere.com/consoles/) aus: +Change it to this: -``` -$ cd my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic -[...] +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} ``` -* Springe nun noch schnell auf den [Web-Tab](https://www.pythonanywhere.com/web_app_setup/) und klicke auf **Reload**. +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## Eins noch: Zeit für das Deployment! + +Mal sehen, ob das alles auch auf PythonAnywhere funktioniert. Zeit für ein weiteres Deployment! + +* Checke als Erstes deinen neuen Code ein und lade ihn auf GitHub hoch: + +{% filename %}command-line{% endfilename %} + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Dann führe Folgendes in der [PythonAnywhere Bash-Konsole](https://www.pythonanywhere.com/consoles/) aus: + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Springe nun noch schnell auf den [Web-Tab](https://www.pythonanywhere.com/web_app_setup/) und klicke auf **Reload**. -Und das war's! Glückwunsch :) +Und das war's! Glückwunsch :) \ No newline at end of file diff --git a/de/django_installation/README.md b/de/django_installation/README.md index d67d2c5853c..c9c5a8fd17f 100644 --- a/de/django_installation/README.md +++ b/de/django_installation/README.md @@ -1,5 +1,7 @@ # Django Installation -> **Hinweis:** Falls du dich bereits durch die Installationsschritte gearbeitet hast, dann hast du das Folgende bereits getan - du kannst direkt mit dem nächsten Kapitel fortfahren! +> **Hinweis** Wenn du ein Chromebook verwendest, überspringe bitte dieses Kapitel und folgen den Anweisungen im [Chromebook Setup](../chromebook_setup/README.md). +> +> **Hinweis:** Falls du dich bereits durch die Installationsschritte gearbeitet hast, gibt es keinen Grund dies erneut zu tun - du kannst direkt zum nächsten Kapitel springen! -{% include "/django_installation/instructions.md" %} +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/de/django_installation/instructions.md b/de/django_installation/instructions.md index 00e8468643d..0a8074d2495 100644 --- a/de/django_installation/instructions.md +++ b/de/django_installation/instructions.md @@ -1,98 +1,150 @@ -> Ein Teil dieses Kapitels basiert auf dem Tutorial der Geek Girls Carrots (http://django.carrots.pl/). +> Ein Teil dieser Sektion basiert auf den Tutorials von Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). > -> Teile dieses Kapitels basieren auf dem [django-marcador Tutorial](http://django-marcador.keimlink.de/) lizenziert unter Creative Commons Attribution-ShareAlike 4.0 International License. Das django-marcador Tutorial von Markus Zapke-Gründemann et al. ist urheberrechtlich geschützt. +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Für das "django-marcador Tutorial" liegt das Urheberrecht bei Markus Zapke-Gründemann et al. ## Virtuelle Umgebung -Bevor wir mit der Installation von Django beginnen, lernen wir ein sehr hilfreiches Tool kennen, das uns hilft, unsere Arbeitsumgebung zum Coden sauber zu halten. Es ist möglich, diesen Schritt zu überspringen, aber wir legen ihn dir dennoch besonders ans Herz. Mit dem bestmöglichen Setup zu starten, wird dir in der Zukunft eine Menge Frust ersparen! +Bevor wir mit der Installation von Django beginnen, lernen wir ein sehr hilfreiches Tool kennen, das uns hilft, unsere Arbeitsumgebung zum Coden sauber zu halten. Es ist möglich diesen Schritt zu überspringen, aber wir legen ihn dir dennoch besonders ans Herz. Mit dem bestmöglichen Setup zu starten, wird dir in der Zukunft eine Menge Frust ersparen! Wir erzeugen eine virtuelle Arbeitsumgebung - ein **virtual environment** oder auch *virtualenv*. Eine virtuelle Umgebung wird dein Python/Django-Setup für ein einzelnes Projekt isolieren. Das bedeutet, dass deine Änderungen an einem Website-Projekt keine anderen Projekte, an welchen du auch gerade entwickelst, beeinträchtigen. Klingt nützlich, oder? -Du musst nur das Verzeichnis festlegen, in dem du das `virtualenv` erstellen willst; zum Beispiel dein Home-Verzeichnis. Auf Windows ist dies `C:\Users\Name` (`Name` ist dein Anmeldename/Login). +Du musst nur das Verzeichnis festlegen, in dem du das `virtualenv` erstellen willst; zum Beispiel dein Home-Verzeichnis. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. In diesem Tutorial erstellen wir darin ein neues Verzeichnis `djangogirls`: -```bash -$ mkdir djangogirls -$ cd djangogirls -``` +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + Wir nennen die virtuelle Umgebung `myvenv`. Das Kommando dazu lautet dann: -```bash -$ python3 -m venv myvenv -``` +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} -### Windows + C:\Users\Name\djangogirls> python -m venv myvenv + -Um ein neues `virtualenv` zu erstellen, öffnest Du die Konsole (das kennst Du schon aus einem vorangegangenen Kapitel) und gibst `C:\Python35\python -m venv myvenv` ein. Das sieht dann so aus: +Where `myvenv` is the name of your `virtualenv`. Du kannst auch andere Namen benutzen. Aber denk daran: nur Kleinbuchstaben, keine Leerzeichen, Akzente oder andere Sonderzeichen. It is also good idea to keep the name short – you'll be referencing it a lot! -```bash -C:\Users\Name\djangogirls> C:\Python35\python -m venv myvenv -``` + -`C:\Python35\python` ist das Verzeichnis in das Du zuvor Python installiert hast. `myvenv` ist der Name deiner neuen virtuellen Arbeitsumgebung, deinem neuen `virtualenv`. Du kannst auch andere Namen benutzen. Aber denk daran: nur Kleinbuchstaben, keine Leerzeichen, Akzente oder andere Sonderzeichen. Kurze Namen eignen sich gut, denn Du wirst sie oft benutzen bzw. eingeben müssen! + -### Linux und OS X +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: -Eine `virtualenv` auf Linux oder OS X anzulegen, heißt lediglich `python3 -m venv myvenv` einzugeben. Fertig. So sieht das dann aus: +{% filename %}command-line{% endfilename %} -```bash -~/djangogirls$ python3 -m venv myvenv -``` + $ python3 -m venv myvenv + -`myvenv` ist der Name deiner neuen virtuellen Arbeitsumgebung, deines neuen `virtualenv`. Andere Namen sind natürlich möglich. Bleibe bei Kleinbuchstaben und verwende keine Leerzeichen. Es ist hilfreich, die Namen kurz zu halten, denn du wirst sie oft benutzen bzw. eingeben müssen! +`myvenv` ist der Name deiner neuen virtuellen Arbeitsumgebung, deines neuen `virtualenv`. Andere Namen sind natürlich möglich. Bleibe bei Kleinbuchstaben und verwende keine Leerzeichen. It is also a good idea to keep the name short as you'll be referencing it a lot! -> **Anmerkung:** Die Einrichtung eines Virtualenv unter Ubuntu wie beschrieben, wird möglicherweise mit der folgenden Fehlermeldung quittiert: ->```bash ->Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 ->``` +> **Hinweis:** Bei manchen Versionen von Debian/Unbuntu kann folgender Fehler auftauchen: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> > > Das zu umgehen, kannst du den `virtualenv`-Befehl verwenden. ->```bash ->~/djangogirls$ sudo apt-get install python-virtualenv ->~/djangogirls$ virtualenv --python=python3.4 myvenv ->``` +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + ## Mit der virtuellen Umgebung arbeiten Die obigen Kommandos erstellen ein Verzeichnis `myvenv` (bzw. den von Dir vergebenen Namen). Es enthält unsere virtuelle Arbeitsumgebung (im Wesentlichen ein paar Verzeichnisse und Dateien). -#### Windows + Starte deine virtuelle Umgebung, indem du eingibst: -```bash -C:\Users\Name\djangogirls> myvenv\Scripts\activate -``` -#### Linux und OS X +{% filename %}command-line{% endfilename %} -Starte deine virtuelle Umgebung, indem du eingibst: + C:\Users\Name\djangogirls> myvenv\Scripts\activate + -```bash -~/djangogirls$ source myvenv/bin/activate -``` +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> -Der Name `myvenv` muss mit dem von Dir gewählten Namen des `virtualenv` übereinstimmen! + -> **Anmerkung:** Manchmal ist das Kommando `source` nicht verfügbar. In diesen Fällen geht es auch so: ->```bash ->~/djangogirls$ . myvenv/bin/activate ->``` + -Dein `virtualenv` wurde erfolgreich erstellt, wenn der Prompt der Konsole so aussieht: +Starte deine virtuelle Umgebung, indem du eingibst: -```bash -(myvenv) C:\Users\Name\djangogirls> -``` +{% filename %}command-line{% endfilename %} -oder: + $ source myvenv/bin/activate + -```bash -(myvenv) ~/djangogirls$ -``` +Der Name `myvenv` muss mit dem von Dir gewählten Namen des `virtualenv` übereinstimmen! + +> **Anmerkung:** Manchmal ist das Kommando `source` nicht verfügbar. In diesen Fällen geht es auch so: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> -Die Zeile sollte mit dem Prefix `(myvenv)` beginnen! + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. In Deiner neuen virtuellen Umgebung wird automatisch die richtige Version von `python` verwendet. Du kannst also `python` statt `python3` eingeben. @@ -100,30 +152,50 @@ Ok, jetzt ist die erforderliche Umgebung startklar und wir können endlich Djang ## Django Installation -Da dein `virtualenv` jetzt gestartet ist, kannst du Django mit `pip` installieren. +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. -Bevor wir das tun, versichern wir uns, dass wir die neueste Version von `pip` installiert haben, die Software, mit welcher wir Django installieren werden: +{% filename %}command-line{% endfilename %} -```bash -(myvenv) ~$ pip install --upgrade pip -``` + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + -Gib in die Konsole `pip install django~=1.10.0` ein. + -```bash -(myvenv) ~$ pip install django~=1.10.0 -Collecting django~=1.10.0 - Downloading Django-1.10.4-py2.py3-none-any.whl (6.8MB) -Installing collected packages: django -Successfully installed django-1.10.4 -``` +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Erstelle ein neues virtualenv in einem neuen Verzeichnis, lösche danach das alte und wiederhohle den oben genannten Befehl. (Das Verzeichnis des virtualenv zu verschieben funktioniert dabei nicht da virtualenv absolute Pfade verwendet.) -Für Windows + -> Wenn du auf einem Windows-Rechner einen Fehler bekommst beim Aufruf von pip, dann prüfe, ob dein Pfad Leerzeichen, Akzente oder Sonderzeichen enthält (`C:\Users\User Name\djangogirls`). Wenn das der Fall ist, dann verschiebe es an einen anderen Ort ohne Leerzeichen, Akzente oder Sonderzeichen (empfohlen: `C:\djangogirls`). Danach versuchst du die Installation am neuen Ort noch einmal. + -Für Linux +> Es kann sein das deine Befehlszeile einfriert wenn du versuchst Django zu installieren. Sollte das passieren nutze folgenden Befehl anstelle des oben angegebenen: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + > Für pip mit Ubuntu 12.04 kann es zu folgendem Fehler kommen. Ruf dann `python -m pip install -U --force-reinstall pip` auf, um die Installation von pip im virtualenv zu reparieren. -Das war's! Du bist nun (endlich) bereit, deine erste Django Anwendung zu starten! + + +Das war's! Du bist nun (endlich) bereit, deine erste Django Anwendung zu starten! \ No newline at end of file diff --git a/de/django_models/README.md b/de/django_models/README.md index 5e30ba31426..7dc27a73939 100644 --- a/de/django_models/README.md +++ b/de/django_models/README.md @@ -4,31 +4,29 @@ Wir erstellen jetzt etwas, damit wir alle Posts von unserem Blog speichern könn ## Objekte -Eine Herangehensweise an das Programmieren ist das so genannte `objektorientierte Programmieren`. Die Idee dahinter ist, dass wir Dinge und ihre Interaktionen untereinander modellieren können und nicht alles als langweilige Kette von Programmbefehlen hintereinander aufschreiben müssen. +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. Was ist denn nun ein Objekt? Ein Objekt ist eine Sammlung von Eigenschaften und Aktionsmöglichkeiten, das anhand einer Vorlage (Klasse) erstellt wird. Das klingt erst einmal komisch, aber hier haben wir gleich ein Beispiel. -Wenn wir zum Beispiel eine Katze modellieren wollen, erschaffen wir eine Objektvorlage `Katze`, eine Art Blaupause oder Schema, nach welcher zukünftig jedes spezifische Katzenobjekt erstellt werden kann. Die Vorlage beschreibt typische Eigenschaften von Katzen, z.B. `farbe`, `alter`, `stimmung` (beispielsweise gut, schlecht oder müde ;)), `besitzer` (der wiederum durch ein `Person`-Objekt repräsentiert wird oder die Eigenschaft bleibt, im Falle eines Streuners, leer). +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). -Jedes Objekt einer `Katze` soll natürlich auch einige Aktionsmöglichkeiten besitzen: `schnurren`, `kratzen` oder `füttern` (hier bekäme die Katze ein bisschen `Katzenfutter`, welches wieder durch ein eigenes Objekt mit Eigenschaften, wie zum Beispiel `Geschmack`, repräsentiert sein könnte). +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). -``` -Katze --------- -farbe -alter -stimmung -besitzerin -schnurren() -kratzen() -fuettern(katzen_futter) -``` + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + -``` -Katzenfutter --------- -geschmack -``` + CatFood + -------- + taste + Der Gedanke dahinter ist also, echte Dinge mit Hilfe von Eigenschaften (genannt `Objekteigenschaften`) und Aktionsmöglichkeiten (genannt `Methoden`) im Programmcode zu beschreiben). @@ -36,17 +34,16 @@ Wie also modellieren wir Blogposts? Schließlich wollen wir ja einen Blog bauen, Wir müssen folgende Fragen beantworten: Was ist ein Blogpost? Welche Eigenschaften sollte er haben? -Nun, zum einen braucht unser Blogpost Text mit einem Inhalt und einen Titel, oder? Außerdem wäre es schön zu wissen, wer ihn geschrieben hat - wir brauchen also noch einen Autor. Schließlich wollen wir wissen, wann der Post geschrieben und veröffentlicht wurde. +Nun, zum einen braucht unser Blogpost Text mit einem Inhalt und einen Titel, oder? It would be also nice to know who wrote it – so we need an author. Schließlich wollen wir wissen, wann der Post geschrieben und veröffentlicht wurde. -``` -Post --------- -title -text -author -created_date -published_date -``` + Post + -------- + title + text + author + created_date + published_date + Was für Dinge könnte man mit einem Blogpost machen? Es wäre schön, wenn wir eine `Methode` hätten, die den Post veröffentlicht, nicht wahr? @@ -58,41 +55,48 @@ Da wir jetzt wissen, was wir erreichen wollen, können wir nun damit anfangen, e Da wir jetzt in etwa wissen, was ein Objekt ist, wollen wir ein Django-Model, eine Vorlage, für unsere Blogposts anlegen, nach welcher wir zukünftig unsere Blogpostobjekte erstellen können. -Ein Model in Django ist ein spezielles Konstrukt, das in unserer Datenbank gespeichert werden kann. Eine Datenbank ist eine Sammlung von Daten. Dies ist ein Ort, an dem du Informationen zu Benutzern, deinen Blogposts usw. speichern wirst. Wir benutzen dafür eine SQLite-Datenbank. Das ist die Voreinstellung in Django - für uns wird das erst einmal ausreichen. +A model in Django is a special kind of object – it is saved in the `database`. Eine Datenbank ist eine Sammlung von Daten. Dies ist ein Ort, an dem du Informationen zu Benutzern, deinen Blogposts usw. speichern wirst. Wir benutzen dafür eine SQLite-Datenbank. This is the default Django database adapter – it'll be enough for us right now. -Du kannst dir ein Model wie eine Tabelle mit Spalten ("Feldern", Englisch "fields") und Zeilen (Datensätzen) vorstellen. +Du kannst dir ein Model wie eine Tabelle mit Spalten ("Feldern", englisch "fields") und Zeilen (Datensätzen) vorstellen. ### Eine Applikation für unseren Blog Um unsere Webseite aufgeräumt zu halten, werden wir eine eigene Anwendung für unser Projekt erstellen, wir nennen das eine Applikation. Wir wollen uns gleich daran gewöhnen, alles ordentlich und sortiert zu halten. Um eine Applikation zu erstellen, müssen wir das folgende Kommando in der Konsole ausführen (wieder in dem `djangogirls`-Verzeichnis, in dem die `manage.py`-Datei liegt): -``` -(myvenv) ~/djangogirls$ python manage.py startapp blog -``` +{% filename %}Mac OS X and Linux:{% endfilename %} -Wie du sehen kannst, wurde ein neues `blog`-Verzeichnis erstellt, welches schon einige Dateien enthält. Das Verzeichnis und die Dateien unseres Projektes sollten jetzt so aussehen: + (myvenv) ~/djangogirls$ python manage.py startapp blog + -``` -djangogirls -├── blog -│   ├── __init__.py -│   ├── admin.py -│   ├── apps.py -│   ├── migrations -│   │   └── __init__.py -│   ├── models.py -│   ├── tests.py -│   └── views.py -├── db.sqlite3 -├── manage.py -└── mysite - ├── __init__.py - ├── settings.py - ├── urls.py - └── wsgi.py -``` +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: -Nach dem Erstellen der Applikation müssen wir Django noch sagen, dass diese auch genutzt werden soll. Das können wir in der Datei `mysite/settings.py` einstellen. Wir suchen den Eintrag `INSTALLED_APPS` und fügen darin die Zeile `'blog',` direkt über der schließenden Klammer `)` ein. Das sollte dann so aussehen: + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} ```python INSTALLED_APPS = [ @@ -108,9 +112,11 @@ INSTALLED_APPS = [ ### Das Blogpost-Model -Alle Models unserer Applikation werden in der `blog/models.py`-Datei definiert. Dies ist also der richtige Platz für unser Blogpost-Model. +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: -Lass uns `blog/models.py` öffnen, lösche alles darin und schreibe Code wie diesen: +{% filename %}blog/models.py{% endfilename %} ```python from django.db import models @@ -118,7 +124,7 @@ from django.utils import timezone class Post(models.Model): - author = models.ForeignKey('auth.User') + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) title = models.CharField(max_length=200) text = models.TextField() created_date = models.DateTimeField( @@ -134,53 +140,60 @@ class Post(models.Model): return self.title ``` -> Kontrolliere nochmal, dass du zwei Unterstriche (`__`) vor und hinter dem `str` gesetzt hast. Diese Konvention wird häufig in Python benutzt und manchmal nennen wir es "dunder" (kurz für "double-underscore"). +> Double-check that you use two underscore characters (`_`) on each side of `str`. Diese Konvention wird häufig in Python benutzt und manchmal nennen wir es "dunder" (kurz für "double-underscore"). -Es sieht kompliziert aus, oder? Aber keine Sorge, wir werden erklären, was diese Zeilen bedeuten! +It looks scary, right? But don't worry – we will explain what these lines mean! -Die Zeilen, die mit `from` oder `import` beginnen, sind Anweisungen, um Sachen aus anderen Dateien mitzunutzen. Anstatt häufig genutzten Code in jede Datei einzeln zu kopieren, binden wir ihn ein mit: `from... import ...`. +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. -`class Post(models.Model):` - Diese Zeile definiert unser Model). +`class Post(models.Model):` – this line defines our model (it is an `object`). -* `class` ist ein spezielles Schlüsselwort, womit wir angeben, dass wir hier eine Klasse, eine Vorlage für zukünftige Objekte, definieren wollen. -* `Post` ist der Name unseres Models. Wir können ihm auch einen anderen Namen geben (aber wir müssen Sonderzeichen und Leerzeichen vermeiden). Beginne einen Klassennamen immer mit einem Großbuchstaben. -* `models.Model` gibt an, dass das Post-Model ein Django-Model ist, so weiß Django, dass es in der Datenbank gespeichert werden soll. +- `class` ist ein spezielles Schlüsselwort, womit wir angeben, dass wir hier eine Klasse, eine Vorlage für zukünftige Objekte, definieren wollen. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` gibt an, dass das Post-Model ein Django-Model ist, so weiß Django, dass es in der Datenbank gespeichert werden soll. -Jetzt definieren wir die Eigenschaften, über welche wir gesprochen haben: `title`, `text`, `created_date`, `published_date` und `author`. Um dies zu tun, müssen wir einen Typen für jedes Feld definieren. (Ist es Text? Eine Zahl? Ein Datum? Eine Beziehung zu einem anderen Objekt, z.B. ein Benutzer?). +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) -* `models.CharField` - so definierst du ein Textfeld mit einer limitierten Anzahl von Zeichen. -* `models.TextField` - so definierst du ein langes Textfeld ohne Limit. Klingt doch perfekt für unsere Blogpostinhalte, oder? -* `models.DateTimeField` - ein Feld für ein Datum und eine Uhrzeit. -* `models.ForeignKey` - definiert eine Verlinkung zu einem anderen Model. +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. -Wir werden nicht den gesamten Code hier erklären, da es einfach zu lange dauern würde. Du solltest einen Blick in die offizielle Django-Dokumentation werfen, wenn du mehr über Modelfelder und darüber wissen möchtest, wie man auch andere Dinge als die oben beschriebenen definiert (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). -Was ist mit `def publish(self):`? Es ist genau die `publish`-Methode zum Veröffentlichen unserer Blogposts, über die wir vorher bereits sprachen. `def` zeigt an, dass es sich nachfolgend um eine Funktion/Methode handelt und `publish` ist der Name der Methode. Du kannst den Namen der Methode auch ändern, wenn du das möchtest. Die Benennungsregel ist, dass wir Kleinbuchstaben und Unterstriche statt Leerzeichen verwenden. Eine Methode, welche den Durchschnittspreis berechnet, könnte zum Beispiel `calculate_average_price` genannt werden. +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. -Methoden geben oftmals etwas zurück (english: `return`). Es gibt ein Beispiel dafür in der `__str__` Methode. In diesem Szenario, wenn wir `__str__()` aufrufen bekommen wir einen Text (**string**) mit einem Post-Titel zurück. +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. -Wenn dir über Methoden noch etwas nicht klar ist, dann zögere nicht, deinen Coach zu fragen! Wir wissen, dass es kompliziert ist, vor allem, wenn du gleichzeitig lernst, was Objekte und Funktionen sind. Aber hoffentlich sieht es für dich jetzt etwas weniger nach Magie aus! +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! ### Tabellen für Models in deiner Datenbank erstellen -Als letzten Schritt wollen wir unser neues Model der Datenbank hinzufügen. Dazu müssen wir Django klarmachen, dass wir einige Änderungen an unserem Model vorgenommen haben (wir haben es gerade erst kreiert!). Gib in deine Konsole `python manage.py makemigrations blog` ein. Das sieht dann so aus: +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: -``` -(myvenv) ~/djangogirls$ python manage.py makemigrations blog -Migrations for 'blog': - blog/migrations/0001_initial.py: - - Create model Post -``` +{% filename %}command-line{% endfilename %} -Django hat für uns eine Migrationsdatei (mit allen aktuellen Informationen über unser Model) vorbereitet, welche wir jetzt auf unsere Datenbank anwenden müssen. Tippe `python manage.py migrate blog` und der Output sollte sein: + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + -``` -(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 -``` +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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! Unser Post-Model ist ab sofort in unserer Datenbank gespeichert! Es wäre doch schön, zu wissen, wie es aussieht, oder? Springe zum nächsten Kapitel und schau es dir an! +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/de/django_orm/README.md b/de/django_orm/README.md index 234d6b15cfb..e5c87af1954 100644 --- a/de/django_orm/README.md +++ b/de/django_orm/README.md @@ -4,7 +4,7 @@ In diesem Kapitel lernst du, wie sich Django mit der Datenbank verbindet und Dat ## Was ist ein QuerySet? -Ein QuerySet ist im Wesentlichen eine Liste von Objekten eines bestimmten Models. Mit dem QuerySet kann man Daten aus der Datenbank auslesen, filtern und ordnen. +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. Am besten wir sehen uns das an einem Beispiel an. Versuchen wir's? @@ -12,23 +12,27 @@ Am besten wir sehen uns das an einem Beispiel an. Versuchen wir's? Öffne deine lokale Konsole (nicht in PythonAnywhere) und tippe dieses Kommando ein: -``` -(myvenv) ~/djangogirls$ python manage.py shell -``` +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + Das sollte angezeigt werden: +{% filename %}command-line{% endfilename %} + ```python -(InteractiveConsole) ->>> +(InteractiveConsole) >>> ``` -Du befindest dich jetzt in Djangos interaktiver Konsole. Das ist fast das gleiche wie die Python-Prompt, aber besitzt etwas zusätzliche Django-Magie :) . Natürlich sind alle Python Kommandos hier trotzdem vorhanden. +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. ### Alle Objekte Zunächst wollen wir alle unsere Blogposts ansehen. Das kannst du mit folgendem Kommando erreichen: +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.all() Traceback (most recent call last): @@ -36,60 +40,76 @@ Traceback (most recent call last): NameError: name 'Post' is not defined ``` -Ups! Das gibt einen Fehler. Die Konsole sagt uns, dass es noch keine Posts gibt. Das stimmt! Wir haben vergessen, diese vorher zu importieren! +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} ```python >>> from blog.models import Post ``` -Das lässt sich einfach ändern: Wir importieren `Post` aus `blog.models`. Jetzt versuchen wir nochmal, alle Posts anzeigen zu lassen: +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.all() , ]> ``` -Das ist die Liste, die wir vorhin erstellt haben! Wir haben diese Posts über die Django Admin Oberfläche erstellt. Aber jetzt wollen wir mit Python neue Einträge erstellen, also wie machen wir das? +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? ### Objekt erstellen So erstellst du ein neues Post-Objekt in der Datenbank: +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.create(author=me, title='Sample title', text='Test') ``` -Allerdings fehlt noch eine Zutat: `me`. Wir müssen eine Instanz des Models `User` als Autor übergeben. Wie macht man das? +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? Als Erstes müssen wir das User Model importieren: +{% filename %}command-line{% endfilename %} + ```python >>> from django.contrib.auth.models import User ``` Welche User sind in unserer Datenbank vorhanden? Finde es damit heraus: +{% filename %}command-line{% endfilename %} + ```python >>> User.objects.all() ]> ``` -Das ist der Superuser, den wir vorhin erstellt haben! Lass uns jetzt eine Instanz des Users erstellen: +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} ```python >>> me = User.objects.get(username='ola') ``` -Wie du siehst, haben wir jetzt ein `User`-Objekt mit einem `username` 'ola'. Schön! Natürlich verwendest du hier deinen eigenen Benutzernamen. +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. Jetzt können wir schließlich unseren Post erstellen: +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.create(author=me, title='Sample title', text='Test') ``` Super! Wollen wir nachsehen, ob es funktioniert hat? +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.all() , , ]> @@ -99,27 +119,33 @@ Da ist er, ein weiterer Post in der Liste! ### Mehrere Posts hinzufügen -Du kannst jetzt noch ein bisschen damit rumprobieren und noch weitere Posts hinzufügen. Erstelle noch zwei oder drei weitere und geh dann zum nächsten Punkt. +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. ### Objekte filtern -Eine wichtige Eigenschaft von QuerySets ist, dass die Einträge gefiltert werden können. Zum Beispiel wollen wir alle Posts des Users Ola finden. Dafür nehmen wir `filter` statt `all` in `Post.objects.all()`. In Klammern schreiben wir die Bedingung(en), die erfüllt werden müssen, damit ein Blogpost in unser Queryset kommt. So soll jetzt z.B. `author` gleich `me` sein, damit nur die Blogposts des Autors "me" herausgefiltert werden. In Django schreiben wir deshalb: `author=me`. Jetzt sieht unser Code folgendermaßen aus: +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. Dafür nehmen wir `filter` statt `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Jetzt sieht unser Code folgendermaßen aus: + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(author=me) [, , , ] ``` -Oder vielleicht wollen wir alle Posts haben, die das Wort "title" im `title`-Feld haben? +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(title__contains='title') [, ] ``` -> **Anmerkung:** Zwischen `title` und `contains` befinden sich zwei Unterstriche (`__`). Das ORM von Django nutzt diese Syntax, um Feldnamen ("title") und Operationen oder Filter ("contains") voneinander zu trennen. Wenn du nur einen Unterstrich benutzt, bekommst du einen Fehler wie "FieldError: Cannot resolve keyword title_contains". +> **Anmerkung:** Zwischen `title` und `contains` befinden sich zwei Unterstriche (`__`). Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". -Du kannst auch eine Liste aller bereits publizierten Posts erhalten, indem wir nach allen Posts suchen, deren `published_date` in der Vergangenheit liegt: +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} ```python >>> from django.utils import timezone @@ -127,19 +153,25 @@ Du kannst auch eine Liste aller bereits publizierten Posts erhalten, indem wir n [] ``` -Unglücklicherweise ist der Post, den wir über die Python-Konsole hinzugefügt haben, noch nicht veröffentlicht. Das können wir ändern! Als Erstes holen wir eine Instanz des Posts, den wir veröffentlichen wollen: +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} ```python >>> post = Post.objects.get(title="Sample title") ``` -Dann publizieren wir ihn mit unserer `publish`-Methode! +Dann publizieren wir ihn mit unserer `publish`-Methode: + +{% filename %}command-line{% endfilename %} ```python >>> post.publish() ``` -Jetzt versuch, eine Liste von veröffentlichten Posts zu bekommen (drücke dreimal "Pfeil nach oben" und `enter`): +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(published_date__lte=timezone.now()) @@ -150,6 +182,8 @@ Jetzt versuch, eine Liste von veröffentlichten Posts zu bekommen (drücke dreim Mit den QuerySets kannst du eine Liste auch nach bestimmten Kriterien ordnen. Lass uns das mit dem `created_date` Feld ausprobieren: +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.order_by('created_date') [, , , ] @@ -157,6 +191,8 @@ Mit den QuerySets kannst du eine Liste auch nach bestimmten Kriterien ordnen. La Wir können die Reihenfolge auch umdrehen, indem wir "`-`" davor schreiben: +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.order_by('-created_date') [, , , ] @@ -166,15 +202,15 @@ Wir können die Reihenfolge auch umdrehen, indem wir "`-`" davor schreiben: Du kannst auch QuerySets kombinieren, indem du sie **verkettest**: -``` ->>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') -``` + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + Dies ist wirklich mächtig und lässt dich ziemlich komplexe Abfragen schreiben. Cool! Jetzt bist du bereit für den nächsten Teil! Um die Konsole zu schließen, schreib das: +{% filename %}command-line{% endfilename %} + ```python >>> exit() -$ -``` +``` \ No newline at end of file diff --git a/de/django_start_project/README.md b/de/django_start_project/README.md index 7c442e9f1b6..a4e518fe360 100644 --- a/de/django_start_project/README.md +++ b/de/django_start_project/README.md @@ -1,47 +1,61 @@ # Dein erstes Django-Projekt! -> Teile dieses Kapitels basieren auf den Tutorials der 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). > -> Teile dieses Kapitels basieren auf dem [django-marcador Tutorial](http://django-marcador.keimlink.de/) lizenziert unter Creative Commons Attribution-ShareAlike 4.0 International License. Für das "django-marcador Tutorial" liegt das Urheberrecht bei Markus Zapke-Gründemann et al. +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Für das "django-marcador Tutorial" liegt das Urheberrecht bei Markus Zapke-Gründemann et al. - -Wir werden einen einfachen Blog erstellen! +We're going to create a small blog! Der erste Schritt ist, ein neues Django-Projekt zu starten. Im Grunde bedeutet das, dass wir einige Skripte ausführen werden, die Django zur Verfügung stellt, um ein Skelett eines Django-Projekts für uns zu erzeugen. Das Projekt beinhaltet einen Haufen von Verzeichnissen und Dateien, die wir später verwenden werden. Die Namen einiger Dateien und Verzeichnisse sind sehr wichtig für Django. Die Dateien, die erstellt werden, solltest du nicht umbenennen. Sie an eine andere Stelle zu verschieben, ist auch keine gute Idee. Django muss zwingend eine gewisse Struktur erhalten, um wichtige Dinge wiederzufinden. -> Denk daran, alles in der "Virtualenv"-Umgebung auszuführen. Wenn du kein Präfix `(Myvenv)` in deiner Konsole siehst, musst du deine Virtualenv-Umgebung aktivieren. Wie das gemacht wird, erklären wir im Kapitel **Django-Installation**, im Abschnitt **Arbeiten mit Virtualenv**. Gib `myvenv\Scripts\activate` in Windows oder `source myvenv/bin/activate` in Mac OS / Linux ein, um die Umgebung zu aktivieren. +> Denk daran, alles in der "Virtualenv"-Umgebung auszuführen. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. Wie das gemacht wird, erklären wir im Kapitel **Django-Installation**, im Abschnitt **Arbeiten mit Virtualenv**. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. -In deiner MacOS- oder Linux-Konsole solltest du den folgenden Befehl ausführen; **vergiss nicht, den Punkt `.` am Ende** einzufügen: + -``` -(myvenv) ~/djangogirls$ django-admin startproject mysite . -``` +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** -Unter Windows; **vergiss nicht, den Punkt `.` am Ende** einzufügen: +{% filename %}command-line{% endfilename %} -``` -(myvenv) C:\Users\Name\djangogirls> django-admin.py startproject mysite . -``` + (myvenv) ~/djangogirls$ django-admin startproject mysite . + -> Der Punkt `.` ist sehr wichtig, weil er dem Skript mitteilt, dass Django in deinem aktuellen Verzeichnis installiert werden soll. (der Punkt `.` ist eine Schnellreferenz dafür) +> Der Punkt `.` ist sehr wichtig, weil er dem Skript mitteilt, dass Django in deinem aktuellen Verzeichnis installiert werden soll. (der Punkt `.` ist eine Schnellreferenz dafür). > -> **Hinweis:** Wenn du die oben angegebenen Kommandos eingibst, denk dran, tippe nur das ein, was mit `django-admin` oder `django-admin.py` anfängt. `(myvenv) ~/djangogirls$` und `(myvenv) C:\Users\Name\djangogirls>` sind nur Teile von dem, was dir in der Eingabeaufforderung angezeigt wird, wenn die Konsole auf deine Eingabe wartet. +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> Der Punkt `.` ist sehr wichtig, weil er dem Skript mitteilt, dass Django in deinem aktuellen Verzeichnis installiert werden soll. (der Punkt `.` ist eine Schnellreferenz dafür). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + `django-admin.py` ist ein Skript, welches Verzeichnisse und Dateien für dich erstellt. Du solltest jetzt eine Verzeichnisstruktur haben, die folgendermaßen aussieht: -``` -djangogirls -├───manage.py -└───mysite - settings.py - urls.py - wsgi.py - __init__.py -``` + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + -`manage.py` ist ein Script, das das Management deines Projektes unterstützt. Mit dem Script bist du unter anderem in der Lage, den Webserver auf deinem Rechner zu starten, ohne etwas Weiteres installieren zu müssen. +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. Die Datei `settings.py` beinhaltet die Konfiguration deiner Website. @@ -51,31 +65,59 @@ Lass uns kurz die anderen Dateien vergessen - wir werden sie nicht verändern. D ## Einstellungen anpassen -Wir werden die Einstellungen in `mysite/settings.py` anpassen. Öffne dazu den zuvor installierten Editor. +Wir machen nun ein paar Änderungen in `mysite/settings.py`. Öffne die Datei mit dem Codeeditor, den du vorhin installiert hast. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. -Es wäre schön, wenn die richtige Zeit auf deiner Webseite eingestellt ist. Gehe zu der [wikipedia timezones list](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones) und kopiere deine zutreffende Zeitzone (time zone, TZ). (z.B. `Europe/Berlin`) +Es wäre schön, wenn die richtige Zeit auf deiner Webseite eingestellt ist. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). -Finde in der settings.py die Zeile, welche `TIME_ZONE` enthält und ändere sie zu deiner Zeitzone: +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} ```python TIME_ZONE = 'Europe/Berlin' ``` -Ändere "Europe/Berlin", wenn zutreffend. +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: -Des Weiteren brauchen wir einen Dateipfad für sogenannte "statische" Dateien (static files). Wir werden später im Tutorial genauer klären, was wir darunter verstehen. Gehe ganz ans Ende der Datei und füge unter `STATIC_URL` einen neuen Eintrag `STATIC_ROOT` ein. +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} ```python STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') ``` -## Eine Datenbank erstellen +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 -Es gibt viele verschiedene Datenbanksysteme, in denen wir Daten für unsere Website speichern können. Wir werden das Standard-System `sqlite3` nutzen.. +## Set up a database + +Es gibt viele verschiedene Datenbank Programme, welche die Daten unserer Website verwalten können. Wir werden die Standard Datenbanksoftware nehmen, `sqlite3`. Das sollte schon in der `mysite/settings.py`-Datei eingestellt sein: +{% filename %}mysite/settings.py{% endfilename %} + ```python DATABASES = { 'default': { @@ -87,50 +129,74 @@ DATABASES = { Um eine Datenbank für unseren Blog zu erstellen, müssen wir folgenden Befehl in der Konsole ausführen (Dazu müssen wir in dem `djangogirls`-Verzeichnis sein, in dem sich auch die `manage.py`-Datei befindet). Wenn alles glatt läuft, sollte das so aussehen: -``` -(myvenv) ~/djangogirls$ python manage.py migrate -Operations to perform: - Apply all migrations: auth, admin, contenttypes, sessions -Running migrations: - Rendering model states... DONE - Applying contenttypes.0001_initial... OK - Applying auth.0001_initial... OK - Applying admin.0001_initial... OK - Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK - Applying sessions.0001_initial... OK -``` +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + Und wir sind fertig! Zeit, unseren Webserver zu starten, um zu sehen, ob unsere Website funktioniert! +## Starting the web server + Kontrolliere, dass du in dem Verzeichniss bist, in dem die `manage.py`-Datei liegt (das `djangogirls`-Verzeichnis). Wir starten den Webserver, indem wir in der Konsole `python manage.py runserver` ausführen: -``` -(myvenv) ~/djangogirls$ python manage.py runserver -``` +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + Wenn du Windows benutzt und dies mit dem `UnicodeDecodeError` fehlschläft, verwende diesen Befehl: -``` -(myvenv) ~/djangogirls$ python manage.py runserver 0:8000 -``` +{% filename %}command-line{% endfilename %} -Jetzt wollen wir schauen, ob unsere Website funktioniert: Öffne deinen Browser (Firefox, Chrome, Safari, Edge oder was du sonst nutzt) und gib folgende Adresse ein: + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + -``` -http://127.0.0.1:8000/ -``` +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} -Der Webserver wird deine Eingabeaufforderung übernehmen, bis du ihn wieder stoppst. Um weiterhin Kommandos einzugeben, während er läuft, öffne eine neue Konsole und aktiviere dein Virtualenv. Um den Webserver zu stoppen, wechsel zurück in das Fenster, in dem er läuft und drücke STRG+C - Steuerung und C gleichzeitig (in Windows kann es sein, dass du STRG und Pause drücken musst). + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + Glückwunsch! Du hast gerade deine erste Website erstellt und sie auf deinem Webserver laufen! Ist das nicht toll? ![Es hat funktioniert!](images/it_worked2.png) -Bereit für den nächsten Schritt? Es wird Zeit, ein paar Inhalte hinzuzufügen! +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Bereit für den nächsten Schritt? Es wird Zeit, ein paar Inhalte hinzuzufügen! \ No newline at end of file diff --git a/de/django_templates/README.md b/de/django_templates/README.md index 8a0e14d01b0..659c89e07a0 100644 --- a/de/django_templates/README.md +++ b/de/django_templates/README.md @@ -4,9 +4,9 @@ Es wird Zeit, ein paar Daten anzuzeigen! Django bringt dafür bereits ein paar s ## Was sind Template Tags? -Also, in HTML kann man nicht wirklich Python-Code schreiben, weil es der Browser nicht verstehen würde. Er kennt nur HTML. Wir wissen, dass HTML, im Gegensatz zum dynamischeren Python, eher statisch ist. +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. -Die **Django Template Tags** helfen dabei, Python-Dinge in HTML auszudrücken, so dass man einfach und schnell dynamische Websites erstellen kann. Super! +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! ## Anzeigen des Post-List-Templates @@ -14,6 +14,8 @@ Im vorangegangen Kapitel haben wir unserem Template in der `posts`-Variable eine Um eine Variable in einem Django-Template darzustellen, nutzen wir doppelte, geschweifte Klammern mit dem Namen der Variable darin, so wie hier: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html {{ posts }} ``` @@ -24,15 +26,19 @@ Versuche dies in deinem `blog/templates/blog/post_list.html` Template. Ersetze a Wie du siehst, haben wir nun das: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html , ]> ``` Das heißt, Django versteht es als Liste von Objekten. Kannst du dich noch an die Einführung von Python erinnern, wie man Listen anzeigen kann? Ja, mit for-Schleifen! In einem Django-Template benutzt du sie so: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html {% for post in posts %} - {{ post }} +    {{ post }} {% endfor %} ``` @@ -40,19 +46,21 @@ Versuch das in deinem Template. ![Abbildung 13.2](images/step2.png) -Es funktioniert! Aber wir wollen, dass die Posts so angezeigt werden, wie die statischen Posts, die wir vorhin im **Introduction to HTML** Kapitel erstellt haben. Du kannst HTML und Template Tags mischen. Unser `body` sollte dann so aussehen: +Es funktioniert! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. Du kannst HTML und Template Tags mischen. Unser `body` sollte dann so aussehen: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
+    
+        

published: {{ post.published_date }}

+        

{{ post.title }}

+        

{{ post.text|linebreaksbr }}

+    
{% endfor %} ``` @@ -60,37 +68,39 @@ Es funktioniert! Aber wir wollen, dass die Posts so angezeigt werden, wie die st ![Abbildung 13.3](images/step3.png) -Ist dir aufgefallen, dass wir diesmal eine etwas andere Notation benutzen bei `{{ post.title }}` oder `{{ post.text }}`? Wir greifen auf Daten von jedem Feld unseres `Post`-Models zu. In den Posttexten konvertiert außerdem der `|linebreaks`-Befehl ("pipe") Zeilenumbrüche in Absätze. +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? Wir greifen auf Daten von jedem Feld unseres `Post`-Models zu. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. ## Und zum Schluss -Es wäre gut zu sehen, ob deine Website noch immer im öffentlichen Internet funktioniert, richtig? Lass uns versuchen, unsere Aktualisierungen wieder zu PythonAnywhere hochzuladen. Hier ist eine Zusammenfassung der Schritte... +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… * Schiebe zuerst deinen Code auf GitHub -```bash -$ git status -[...] -$ git add --all . -$ git status -[...] -$ git commit -m "Modified templates to display posts from database." -[...] -$ git push -``` +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + * Dann logg dich wieder bei [PythonAnywhere](https://www.pythonanywhere.com/consoles/) ein und geh zu deiner **Bash-Konsole** (oder starte eine neue) und gib ein: -```bash -$ cd my-first-blog -$ git pull -[...] -``` +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + -* Zum Schluss hüpf noch einmal kurz rüber zum [Web-Tab](https://www.pythonanywhere.com/web_app_setup/) und drück auf **Reload**. Deine Änderungen sollten jetzt live sein! +* Zum Schluss hüpf noch einmal kurz rüber zum [Web-Tab](https://www.pythonanywhere.com/web_app_setup/) und drück auf **Reload**. Deine Änderungen sollten jetzt live sein! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. -Herzlichen Glückwunsch! Du kannst jetzt in der Django Admin Oberfläche neue Posts hinzufügen (denk daran published_date hinzuzufügen!), dann aktualisiere die Site, um zu sehen, ob der neue Post auch erscheint. +Glückwunsch! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. -Funktioniert super? Wir sind stolz auf dich! Steh kurz ein bisschen vom Computer auf. Du hast dir eine Pause verdient :) +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) -![Abbildung 13.4](images/donut.png) +![Abbildung 13.4](images/donut.png) \ No newline at end of file diff --git a/de/django_urls/README.md b/de/django_urls/README.md index 445ebe0a8c9..4f0aeecade0 100644 --- a/de/django_urls/README.md +++ b/de/django_urls/README.md @@ -1,19 +1,21 @@ # Django URLs -Wir sind dabei, unsere erste Website zu erstellen --eine Homepage für unseren Blog! Aber zunächst lernen wir etwas über Django URLs. +Gleich werden wir unsere erste Website basteln: eine Homepage für deinen Blog! Zuerst sollten wir uns jedoch mit Django URLs beschäftigen. ## Was ist eine URL? -Eine URL ist einfach eine Web-Adresse. Jedes Mal, wenn du eine Website besuchst, kannst du eine URL sehen - sie ist in der Adressleiste des Browsers sichtbar (ja! `127.0.0.1:8000` ist eine URL! Und `https://djangogirls.com` ist auch eine URL!). +Eine URL ist einfach eine Web-Adresse. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` ist eine URL! Und `https://djangogirls.org` ist auch eine URL.) ![URL](images/url.png) -Jede Seite im Internet braucht ihre eigene URL. Dadurch weiß deine Applikation, was sie dem Nutzer, der eine URL öffnet, zeigen soll. In Django verwenden wir eine sogenannte `URLconf` (URL- Konfiguration). URLconf ist eine Ansammlung von Mustern, die Django mit der empfangenen URL abgleicht, um die richtige View zu finden, das heißt, um letztlich die richtige Seite für den Nutzer anzuzeigen. +Jede Seite im Internet braucht ihre eigene URL. This way your application knows what it should show to a user who opens that URL. In Django verwenden wir eine sogenannte `URLconf` (URL- Konfiguration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. ## Wie funktionieren URLs in Django? Öffne die `mysite/urls.py`-Datei in deinem Code-Editor nach Wahl und schaue dir an, wie sie aussieht: +{% filename %}mysite/urls.py{% endfilename %} + ```python """mysite URL Configuration @@ -27,37 +29,39 @@ urlpatterns = [ ] ``` -Wie du siehst, hat Django hier schon etwas für uns eingefügt. +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. -Zeilen, die mit `#` anfangen sind Kommentare - das bedeutet, dass diese Zeilen von Python nicht ausgeführt werden. Praktisch, oder? +The admin URL, which you visited in previous chapter, is already here: -Die admin-URL, die du im vorangegangenen Kapitel bereits besucht hast, ist schon da: +{% filename %}mysite/urls.py{% endfilename %} ```python -url(r'^admin/', admin.site.urls), + url(r'^admin/', admin.site.urls), ``` -Für jede URL, die mit `admin/` beginnt, wird Django die entsprechende View finden. Hier wurden einige admin-URLs eingefügt, dadurch wird nicht alles in eine Datei gepackt --es bleibt lesbarer und sauberer. +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. ## Regex Du fragst dich, WIE Django die richtige View zu einer URL findet? Nun, das ist ein bisschen komplizierter. Django benutzt `regex` kurz für "regular expressions" (reguläre Ausdrücke). Regex besteht aus vielen Regeln (wirklich vielen!), aus denen ein Suchschema aufgebaut ist. Da Regexes ein fortgeschrittenes Thema sind, werden wir jetzt nicht im Detail darauf eingehen, wie sie genau funktionieren. -Wenn du trotzdem immer noch verstehen willst, wie wir die Muster erstellt haben, folgt hier ein kleines Beispiel. Wir brauchen nur eine eingeschränkte Menge der vorhandenen Regeln, um das Muster, nach dem wir suchen, auszudrücken, nämlich: +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: -* `^` für den Anfang eines Textes -* `$` für das Ende eines Textes -* `\d` für eine Nummer -* `+` um anzuzeigen, dass das vorhergehende Element mind. 1 mal wiederholt werden soll -* `()` um Teile des Musters zu erfassen +* `^` für den Anfang des Textes +* `$` für den Ende des Textes +* `\d` für eine Zahl +* `+` um zu zeigen, dass das vorherige Objekt mindestens einmal wiederholt werden soll +* `()` to capture part of the pattern -Alles andere in der URL-Definition wird wörtlich genommen. +Anything else in the URL definition will be taken literally. -Jetzt stell dir vor, du hast eine Website mit der Adresse: `http://www.mysite.com/post/12345/` wobei `12345` die Nummer deines Posts ist. +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. -Eigene Views für jeden einzelnen Post zu schreiben, wäre ziemlich nervig. Mit regulären Asudrücken können wir ein Muster erstellen, welches auf die URL passt und die Nummer extrahieren wird: `^post/(\d+)/$`. Lass es uns in kleine Häppchen aufteilen, um zu verstehen, was wir hier genau tun: +Eigene Views für jeden einzelnen Post zu schreiben, wäre ziemlich nervig. Mit regulären Ausdrücken können wir Ausdrücke schreiben, die aus einer URL die Zahlen herausfiltern: `^post/(\d+)/$`. Lass es uns in kleine Häppchen aufteilen, um zu verstehen, was wir hier genau tun: -* **^post/** veranlasst Django, alles in Betracht zu ziehen, das `post/` am Anfang der URL hat (gleich nach `^`) +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) * **(\d+)** steht für eine Zahl (eine oder mehrere Ziffern) und wir wollen diese Zahl erfassen und auswerten * **/** sagt Django, dass ein weiteres `/` Zeichen folgen soll * **$** steht für das Ende der URL mit der Bedeutung, dass nur Zeichenfolgen, die auf `/` enden, dem Muster entsprechen @@ -66,14 +70,17 @@ Eigene Views für jeden einzelnen Post zu schreiben, wäre ziemlich nervig. Mit Es wird Zeit, deine erste URL zu erstellen! Wir wollen, dass 'http://127.0.0.1:8000/' die Homepage unseres Blogs wird und eine Liste unserer Posts zeigt. -Wir wollen auch, dass die `mysite/urls.py`-Datei sauber bleibt. Deshalb importieren wir die URLs unserer Blog-Applikation in die `mysite/urls.py`-Hauptdatei. +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. -Fang damit an, die auskommentierten Zeilen (Zeilen mit `#`) zu löschen und füge die Zeile hinzu, die unsere `blog.urls` in die Haupt-URL importieren wird (`''`). +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. Deine `mysite/urls.py`-Datei sollte jetzt so aussehen: +{% filename %}mysite/urls.py{% endfilename %} + ```python -from django.conf.urls import include, url +from django.conf.urls import include +from django.conf.urls import url from django.contrib import admin urlpatterns = [ @@ -88,33 +95,35 @@ Beim Schreiben von regulären Ausdrücken in Python benutzt man immer das `r` vo ## blog.urls -Erstelle eine neue, leere Datei `blog/urls.py`. Alles klar! Füge nun diese beiden Zeilen hinzu: +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} ```python from django.conf.urls import url from . import views ``` -Hier importieren wir erstmal nur die Methoden von Django und alles aus den `views` unserer `blog` Applikation (wir haben noch keine, aber dazu kommen wir gleich!). +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) Danach können wir unser erstes URL-Pattern hinzufügen: +{% filename %}blog/urls.py{% endfilename %} + ```python urlpatterns = [ url(r'^$', views.post_list, name='post_list'), ] ``` -Hier haben wir nun einen `view` mit dem Namen `post_list` zur `^$`-URL hinzugefügt. Dieser reguläre Ausdruck passt auf einen Anfang `^` gefolgt von einem Ende `$` - das heißt, nur eine leere Zeichenfolge kann dieses Muster erfüllen. Und das ist auch richtig so! Denn die Django URL-Auflösung erkennt 'http://127.0.0.1:8000/' nicht als Teil der URL an. Wenn jemand deine Website mit der Adresse 'http://127.0.0.1:8000/' aufruft, passt dieses Muster (leere Zeichenkette) und Django weiß so, dass `views.post_list` das gewünschte Ziel ist. +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. Und das ist auch richtig so! Denn die Django URL-Auflösung erkennt 'http://127.0.0.1:8000/' nicht als Teil der URL an. Wenn jemand deine Website mit der Adresse 'http://127.0.0.1:8000/' aufruft, passt dieses Muster (leere Zeichenkette) und Django weiß so, dass `views.post_list` das gewünschte Ziel ist. -Der letzte Teil `name='post_list'` ist der Name der URL, die genutzt wird, die View zu identifizieren. Dieser kann identisch mit dem Namen der View sein, kann aber auch etwas total Anderes sein. Wir werden später die benannten URLs in dem Projekt benutzen, daher ist es wichtig, jede URL in der App zu benennen. Wir sollten außerdem versuchen, solche Namen für URLs zu wählen, die einzigartig und einfach zu merken sind. +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. Dieser kann identisch mit dem Namen der View sein, kann aber auch etwas total Anderes sein. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. -Alles klar? Öffne http://127.0.0.1:8000/ in deinem Browser, um das Ergebnis zu sehen. +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. ![Fehler](images/error1.png) -Dort steht nicht mehr "It works"? Keine Sorge, es ist nur eine Fehlerseite. Nichts, wovor man Angst haben muss! Diese Seiten sind eigentlich sehr hilfreich: - -Dort steht, es gibt **no attribute 'post_list'**. Erinnert dich *post_list* an etwas? So haben wir unsere View genannt! Das heißt, dass alles bereits an Ort und Stelle ist, aber wir haben bislang einfach noch keine *View* erzeugt. Keine Sorge, das machen wir gleich. +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. -> Wenn du mehr über Django URLconfs lernen willst, dann öffne die offizielle Dokumentation: https://docs.djangoproject.com/en/1.8/topics/http/urls/ +> Wenn du mehr über Django URLconfs lernen willst, dann öffne die offizielle Dokumentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/de/django_views/README.md b/de/django_views/README.md index f14762cef4c..7b139237d3a 100644 --- a/de/django_views/README.md +++ b/de/django_views/README.md @@ -1,8 +1,8 @@ -# Django Views - Zeit zum Gestalten! +# Django views – time to create! -Es wird jetzt Zeit, den Bug, den wir im letzten Kapitel erzeugt haben, zu beheben :) +Es wird jetzt Zeit, den Bug, den wir im letzten Kapitel erzeugt haben, zu beheben! :) -In der *View* schreiben wir die Logik unserer Anwendung. So werden Informationen aus dem `Model` abgefragt werden, welches du zuvor erzeugt hast und diese werden an ein `Template` weitergeben. Ein Template erzeugen wir im nächsten Kapitel. Views sind Python-Methoden, die ein bisschen komplizierter sind als die, die wir im Kapitel **Introduction to Python** kennengelernt haben. +In der *View* schreiben wir die Logik unserer Anwendung. So werden Informationen aus dem `Model` abgefragt werden, welches du zuvor erzeugt hast und diese werden an ein `Template` weitergeben. Ein Template erzeugen wir im nächsten Kapitel. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. Views kommen in die `views.py` Datei. Wir fügen nun also unsere *Views* zur Datei `blog/views.py` hinzu. @@ -10,27 +10,35 @@ Views kommen in die `views.py` Datei. Wir fügen nun also unsere *Views* zur Dat OK, wir öffnen nun diese Datei und schauen was darin steht: +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render # Create your views here. ``` -Es steht noch nicht viel da. Die einfachste *View* kann folgendermaßen aussehen: +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} ```python def post_list(request): return render(request, 'blog/post_list.html', {}) ``` -Du siehst hier, dass wir eine Methode (`def`) mit dem Namen `post_list` definiert haben. Sie hat den Parameter `request`. In der Methode weisen wir mit `return` eine Rückgabe einer anderen Funktion namens `render` an. Diese wird unser Template `blog/post_list.html` erstellen (man sagt auch "rendern"). +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. -Speichere die Datei, öffne http://127.0.0.1:8000/ im Browser und schau nach, was wir jetzt bekommen. +Save the file, go to http://127.0.0.1:8000/ and see what we've got. Einen anderen Fehler! Lies dir durch, was da steht: ![Fehler](images/error.png) -Logisch: *TemplateDoesNotExist*. Wir haben ja noch kein Template erstellt. Lass uns diesen Bug im nächsten Kapitel beheben! +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! -> Erfahre mehr über Django Views in der offiziellen Dokumentation: https://docs.djangoproject.com/en/1.10/topics/http/views/ +> Erfahre mehr über Django Views in der offiziellen Dokumentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/de/dynamic_data_in_templates/README.md b/de/dynamic_data_in_templates/README.md index 5ac20a5d49c..ed5a6c0f278 100644 --- a/de/dynamic_data_in_templates/README.md +++ b/de/dynamic_data_in_templates/README.md @@ -1,42 +1,51 @@ # Dynamische Daten in Templates -Wir haben nun schon einige Dinge an verschiedenen Orten fertiggestellt: das `Post`-Model ist in der `models.py` definiert, wir haben die `post_list` in der `views.py` und das Template hinzugefügt. Aber wie schaffen wir es nun, dass unsere Posts wirklich im HTML-Template erscheinen? Denn wir wollen ja erreichen, dass bestimmte Inhalte (die in der Datenbank gespeicherten Models) auf schöne Weise in unserem Template anzeigt werden, richtig? +Wir haben nun schon einige Dinge an verschiedenen Orten fertiggestellt: das `Post`-Model ist in der `models.py` definiert, wir haben die `post_list` in der `views.py` und das Template hinzugefügt. Aber wie schaffen wir es nun, dass unsere Posts wirklich im HTML-Template erscheinen? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? -Genau dafür sind die *Views* zuständig: die Verbindung zwischen den Models und den Templates. In unserer `post_list`-View müssen wir die Models adressieren, die wir anzeigen wollen und diese dem Template übergeben. Im Grunde entscheiden wir in der *View*, was (also welches Model) im Template angezeigt wird. +Genau dafür sind die *Views* zuständig: die Verbindung zwischen den Models und den Templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. -Okay, und wie machen wir das jetzt? +OK, so how will we achieve this? Wir öffnen unsere Datei `blog/views.py`. Bisher sieht unsere `post_list`-View folgendermaßen aus: +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render def post_list(request): return render(request, 'blog/post_list.html', {}) + ``` -Erinnerst du dich, als wir davon gesprochen haben, dass wir den Code in verschiedene Dateien einfügen müssen? Jetzt ist es an der Zeit, das Model, dass wir in `models.py` beschrieben haben, einzufügen. Wir fügen den Befehl `from .models import Post` folgendermaßen ein: +Erinnerst du dich, als wir davon gesprochen haben, dass wir den Code in verschiedene Dateien einfügen müssen? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render from .models import Post ``` -Der Punkt nach dem `from` bedeutet *current directory*, also das aktuelle Verzeichnis oder *current application*, aktuelle Anwendung. Da `views.py` und `models.py` im gleichen Verzeichnis liegen, können wir einfach den Punkt `.` und den Namen der Datei (ohne `.py`) benutzen. Dann ergänzen wir für den Import den Namen des Models (`Post`). +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Dann ergänzen wir für den Import den Namen des Models (`Post`). -Und als nächstes? Um tatsächlich Blogposts aus dem `Post` Model anzusprechen, brauchen wir etwas, das `QuerySet` heißt. +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. ## QuerySet -Dir sollte jetzt schon ungefähr klar sein, wie QuerySets funktionieren. Wir haben darüber im Kapitel [Django ORM (QuerySets)](../django_orm/README.md) gesprochen. +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). -Wir wollen nun also eine Liste von Blogposts, die publiziert und nach `published_date` sortiert sind, ausgeben, oder? Das haben wir bereits im Kapitel QuerySets gemacht! +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} ```python Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') -``` +``` -Diesen Code fügen wir jetzt in `blog/views.py` ein, indem wir es zur Funktion `def post_list(request)` hinzufügen: +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render @@ -48,16 +57,16 @@ def post_list(request): return render(request, 'blog/post_list.html', {}) ``` -Beachte, dass wir eine *Variable* für unser QuerySet erstellen: `posts`. Es ist sozusagen der Name unseres QuerySets. Ab jetzt bezeichnen wir das QuerySet mit diesem Namen. - -Ferner benutzt der Code die `timezone.now()`-Funktion, also müssen wir einen Import für `timezone` hinzufügen. +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. -Als Letztes fehlt noch, dass wir das `posts`-QuerySet dem Template übergeben (wie wir es dann anzeigen, wird im nächsten Kapitel erklärt). +Beachte, dass wir eine *Variable* für unser QuerySet erstellen: `posts`. Es ist sozusagen der Name unseres QuerySets. Ab jetzt bezeichnen wir das QuerySet mit diesem Namen. -In der `render`-Funktion haben wir schon einen Parameter `request` (also alles, was wir vom User über das Internet bekommen) und einen Template-Namen`'blog/post_list.html'` angegeben. Der letzte Parameter, der so aussieht: `{}` ist ein Ort, wo wir Informationen, welche das Template nutzt, einfügen können. Wir müssen diesen einen Namen geben (wir verwenden einfach wieder `'posts'` :) ). Es sollte nun so aussehen: `{'posts': posts}`. Bitte achte darauf, dass der Teil vor `:` ein String ist; das heißt, du musst ihn mit Anführungszeichen umschliessen `''`. +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. Wir müssen diesen einen Namen geben (wir verwenden einfach wieder `'posts'`). :) Es sollte nun so aussehen: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. Am Ende sollte deine `blog/views.py` Datei folgendermaßen aussehen: +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render from django.utils import timezone @@ -70,4 +79,4 @@ def post_list(request): Das war's! Nun gehen wir zurück ins Template und zeigen das QuerySet an! -Wenn du mehr über QuerySets in Djago erfahren willst, dann sieh unter diesem Link nach: https://docs.djangoproject.com/en/1.10/ref/models/querysets/ +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/de/extend_your_application/README.md b/de/extend_your_application/README.md index 547329f4bce..a709b1a7d22 100644 --- a/de/extend_your_application/README.md +++ b/de/extend_your_application/README.md @@ -10,35 +10,39 @@ Wir haben bereits ein `Post`-Model, deshalb brauchen wir dieses nicht mehr zur ` ## Erstelle eine Template-Verknüpfung -Wir beginnen damit, einen Link in der `blog/templates/blog/post_list.html`-Datei zu erstellen. Bis jetzt sieht sie so aus: +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% extends 'blog/base.html' %} {% block content %} - {% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
- {% endfor %} -{% endblock content %} +    {% for post in posts %} +        
+            
+                {{ post.published_date }} +            
+            

{{ post.title }}

+            

{{ post.text|linebreaksbr }}

+        
+    {% endfor %} +{% endblock %} ``` {% raw %}Wir wollen einen Link von einem Post-Titel in der Post-Liste zu einer Post-Detailseite haben. Ändern wir `

{{ post.title }}

`, so dass es zu der Detailseite verlinkt:{% endraw %} +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html

{{ post.title }}

``` {% raw %}Es ist an der Zeit, das mysteriöse `{% url 'post_detail' pk=post.pk %}` zu erklären. Wie du dir wahrscheinlich schon denkst, bedeutet `{% %}`, dass wir Django Template Tags verwenden. Dieses Mal verwenden wir eines, dass eine URL für uns erzeugen wird! {% endraw %} -`blog.views.post_detail` ist der Pfad zu einer `post_detail`-View, die wir erstellen wollen. Beachte bitte: `blog` ist der Name unserer App (das Verzeichnis `blog`), `views` kommt aus der `views.py`-Datei und der letzte Teil - `post_detail` - ist der Name der View. +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! -Wenn wir jetzt auf http://127.0.0.1:8000/ gehen, bekommen wir einen Fehler (so wie erwartet, da wir ja noch keine URL oder View für `post_detail` haben). Er wird folgendermaßen aussehen: +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: ![NoReverseMatch error](images/no_reverse_match2.png) @@ -48,7 +52,9 @@ Lass uns eine URL in `urls.py` für unsere `post_detail`-View erstellen! Wir wollen, dass Details unseres ersten Blogposts unter dieser URL angezeigt werden: http://127.0.0.1:8000/post/1/ -Lass uns eine URL in der Datei `blog/urls.py` anlegen, um Django auf die *View* hinzuweisen, genannt `post_detail`, welche einen ganzen Blogpost anzeigen wird. Füge die Zeile `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail')` zu der Datei `blog/urls.py` hinzu. Die Datei sollte so aussehen: +Lass uns eine URL in der Datei `blog/urls.py` anlegen, um Django auf die *View* hinzuweisen, genannt `post_detail`, welche einen ganzen Blogpost anzeigen wird. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. Die Datei sollte so aussehen: + +{% filename %}blog/urls.py{% endfilename %} ```python from django.conf.urls import url @@ -60,13 +66,17 @@ urlpatterns = [ ] ``` -Dieser Teil `^post/(?P[0-9]+)/$` sieht beängstigend aus, aber hab keine Angst - wir erklären es dir: - es beginnt mit `^` --"Der Anfang" -`post/` bedeutet lediglich, die URL sollte nach dem Anfang das Wort **post** und **/** enthalten. So weit, so gut. `(?P[0-9]+)` - dieser Teil ist schwieriger. Er bedeutet, dass Django alles, was hier steht, in einer Variable namens `pk` zu einem View transferiert. `[0-9]` sagt uns, dass hier nur eine Zahl, kein Buchstabe, stehen darf (also alles zwischen 0 und 9). `+`bedeutet, dass hier mindestens eine (oder mehrere) Ziffer(n) stehen müssen. Also so etwas wie `http://127.0.0.1:8000/post//` geht nicht, aber `http://127.0.0.1:8000/post/1234567890/` ist genau richtig! Dann folgt ein `/` - wir brauchen also wieder einen **/** und `$` - "Ende"! +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: -Also wenn du `http://127.0.0.1:8000/post/5/` in deinen Browser eingibst, wird Django verstehen, dass du nach einer *View* suchst, die `post_detail` heißt und wird der *View* übergeben, dass die Variable `pk` gleich `5` lautet. +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. Er bedeutet, dass Django alles, was hier steht, in einer Variable namens `pk` zu einem View transferiert. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+`bedeutet, dass hier mindestens eine (oder mehrere) Ziffer(n) stehen müssen. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! -`pk` ist eine Abkürzung für `primary key`. Diese Bezeichnung wird oft in Django-Projekten benutzt. Du kannst deine Variable aber nennen, wie du willst (denk aber daran: Kleinbuchstaben und `_` anstelle von Leerzeichen). Zum Beispiel anstelle von `(?P[0-9]+)` können wir die Variable `post_id` nehmen, dieser Teil würde also `(?P[0-9]+)` lauten. +Also wenn du `http://127.0.0.1:8000/post/5/` in deinen Browser eingibst, wird Django verstehen, dass du nach einer *View* suchst, die `post_detail` heißt und wird der *View* übergeben, dass die Variable `pk` gleich `5` lautet. -Ok, wir haben ein neues URL-Muster zu der Datei `blog/urls.py` hinzugefügt! Lass uns die Seite http://127.0.0.1:8000/ aktualisieren. Boom! Erneut ein Fehler! Wie erwartet! +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! ![AttributeError](images/attribute_error2.png) @@ -74,38 +84,46 @@ Erinnerst du dich, was der nächste Schritt ist? Natürlich: eine View hinzufüg ## Füge eine View hinzu -Dieses Mal bekommt unsere *View* den extra Parameter `pk`. Unsere *View* muss diesen abfangen, richtig? Also definieren wir unsere Funktion mit `def post_detail(request, pk)`. Beachte, dass wir genau den gleichen Variablennamen benutzen müssen, wie in den URLs festgelegt (`pk`). Eine fehlerhafte Variable führt zu einem Fehler! +This time our *view* is given an extra parameter, `pk`. Unsere *View* muss diesen abfangen, richtig? Also definieren wir unsere Funktion mit `def post_detail(request, pk)`. Beachte, dass wir genau den gleichen Variablennamen benutzen müssen, wie in den URLs festgelegt (`pk`). Eine fehlerhafte Variable führt zu einem Fehler! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: -Jetzt benötigen wir also genau einen bestimmten Blogpost. Diesen finden wir, indem wir ein Queryset folgendermaßen schreiben: +{% filename %}blog/views.py{% endfilename %} ```python Post.objects.get(pk=pk) ``` -Aber bei diesem Code gibt es ein Problem. Wenn es kein `Post`-Objekt mit diesem `primary key` (`pk`) gibt, bekommen wir einen schlimmen Fehler! +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! ![DoesNotExist error](images/does_not_exist2.png) -Das wollen wir nicht! Natürlich stellt uns Django etwas zur Verfügung, um dieses Problem zu umgehen: `get_object_or_404`. Wenn es kein `Post`-Objekt mit einem gegebenen `pk` gibt, wird eine schöne Seite angezeigt (die sogenannte `Page Not Found 404` Seite). +Das wollen wir nicht! Natürlich stellt uns Django etwas zur Verfügung, um dieses Problem zu umgehen: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. ![Page not found](images/404_2.png) Die gute Neuigkeit ist, dass du auch deine eigene `Page not found`-Seite ("Seite nicht gefunden"-Seite) erstellen und diese so hübsch gestalten kannst, wie du willst. Aber da das gerade nicht so wichtig ist, überspringen wir das erst einmal. -Okay, es wird Zeit, die *View* zu unserer `views.py`-Datei hinzuzufügen! +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: -Wir öffnen `blog/views.py` und fügen folgenden Code zu den anderen "from"-Zeilen hinzu: +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render, get_object_or_404 ``` -Am Ende der Datei fügen wir unsere *View* hinzu: +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} ```python def post_detail(request, pk): - post = get_object_or_404(Post, pk=pk) - return render(request, 'blog/post_detail.html', {'post': post}) +    post = get_object_or_404(Post, pk=pk) +    return render(request, 'blog/post_detail.html', {'post': post}) ``` Super. Lass uns nun http://127.0.0.1:8000/ aktualisieren. @@ -118,33 +136,35 @@ Es hat funktioniert! Aber was passiert, wenn du auf den Link im Blog-Titel klick Oh nein! Ein anderer Fehler! Aber wir wissen ja schon, wie wir mit diesem umgehen, oder? Wir müssen ein Template hinzufügen! -## Erzeuge ein Template +## Create a template for the post details Wir erstellen eine Datei in `blog/templates/blog` mit dem Namen `post_detail.html`. Das sieht dann so aus: +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + ```html {% extends 'blog/base.html' %} {% block content %} -
- {% if post.published_date %} -
- {{ post.published_date }} -
- {% endif %} -

{{ post.title }}

-

{{ post.text|linebreaksbr }}

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

{{ post.title }}

+        

{{ post.text|linebreaksbr }}

+    
{% endblock %} ``` Wir erweitern wieder `base.html`. Im `content`-Block wollen wir das Publikationsdatum eines Posts (published_date), falls es existiert, anzeigen und auch den Titel und den Text. Aber wir müssen noch ein paar wichtige Dinge klären, oder? -{% raw %}`{% if ... %} ... {% endif %}` ist ein Template-Tag, das wir nutzen können, um etwas zu überprüfen (erinnerst du dich: `if ...else .. aus dem Kapitel Einführung in Python? In diesem Szenario wollen wir prüfen, ob ein published_date` eines Blogposts leer ist. {% 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 %} -Okay, wir aktualisieren die Seite und sehen, dass `Page not found` nun weg ist. +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. ![Post Detailseite](images/post_detail2.png) @@ -154,25 +174,24 @@ Yeah! Es funktioniert! Es wäre schön zu sehen, ob deine Website noch auf PythonAnywhere funktioniert, richtig? Lass sie uns erneut bereitstellen. -``` -$ 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 -``` +{% filename %}command-line{% endfilename %} -* Dann führe Folgendes in der [PythonAnywhere Bash-Konsole](https://www.pythonanywhere.com/consoles/) aus: + $ 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 + -``` -$ cd my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic -[...] -``` +Dann führe Folgendes in der [PythonAnywhere Bash-Konsole](https://www.pythonanywhere.com/consoles/) aus: + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + -* Springe nun noch schnell auf den [Web-Tab](https://www.pythonanywhere.com/web_app_setup/) und klicke auf **Reload**. +Springe nun noch schnell auf den [Web-Tab](https://www.pythonanywhere.com/web_app_setup/) und klicke auf **Reload**. -Und das war's! Glückwunsch :) +Und das war's! Glückwunsch :) \ No newline at end of file diff --git a/de/how_the_internet_works/README.md b/de/how_the_internet_works/README.md index 0cbd3642233..75440c77c09 100644 --- a/de/how_the_internet_works/README.md +++ b/de/how_the_internet_works/README.md @@ -1,49 +1,47 @@ # Wie das Internet funktioniert -> Tipp: Für dieses Kapitel existiert ein Video: [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc). +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> This chapter is inspired by the talk "How the Internet works" by Jessica McKellar (http://web.mit.edu/jesstess/www/). -> Inspiriert durch den Vortrag "How the Internet works" von Jessica McKellar (http://web.mit.edu/jesstess/www/). - -Wahrscheinlich nutzt du das Internet jeden Tag. Aber weißt du, was passiert, wenn du eine Adresse wie https://djangogirls.org im Browser aufrufst? +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`? Als Erstes solltest du wissen, dass eine Webseite meist nur ein paar Dateien auf der Festplatte sind. Genau wie deine Filme, Mp3s oder Bilder. Das Besondere an Webseiten ist, dass sie aus speziellem Computer-Code bestehen, das sogenannte HTML. Wenn du noch nie etwas mit Programmierung zu tun hattest, kann auch HTML zuerst abschreckend aussehen, aber dein Browser (Chrome, Safari, Firefox, etc.) liebt es. Browser sind so entworfen, dass sie diesen Code verstehen, seinen Anweisungen folgen können und diese Dateien, aus denen deine Website besteht, genau so darstellen, wie du es möchtest. -Wie jede andere Datei auch, muss die HTML-Datei irgendwo auf einer Festplatte gespeichert werden. Für das Internet verwenden wir spezielle, leistungsstarke Computer, sogenannte *Server*. An ihnen sind normalerweise weder Bildschirm, Maus oder Tastatur angeschlossen, weil der Hauptzweck der Server darin besteht, Daten zu speichern und zur Verfügung zu stellen. Sie heißen *Server*, weil sie dem Internet und uns dienen - Englisch: to *serve*. +Wie jede andere Datei auch, muss die HTML-Datei irgendwo auf einer Festplatte gespeichert werden. Für das Internet verwenden wir spezielle, leistungsstarke Computer, sogenannte *Server*. An ihnen sind normalerweise weder Bildschirm, Maus oder Tastatur angeschlossen, weil der Hauptzweck der Server darin besteht, Daten zu speichern und zur Verfügung zu stellen. That's why they're called *servers* – because they *serve* you data. -Okay, aber wie funktioniert dieses Internet jetzt genau? +OK, but you want to know how the Internet looks, right? Wir haben ein Bild gemalt. So sieht es aus: ![Abbildung 1.1](images/internet_1.png) -Ziemliches Durcheinander, oder? Eigentlich ist es ein Netzwerk aus verbundenen Computern (den oben genannten *Servern*). Hunderttausende von Rechnern! Kilometer über Kilometer Kabel rund um die Welt. Auf einer Webseite über Unterseekabel (https://submarinecablemap.com/) kannst du dir ein Bild von der Komplexität des Netzes machen. Hier ist ein Screenshot der Seite: +Ziemliches Durcheinander, oder? In fact it is a network of connected machines (the above-mentioned *servers*). Hunderttausende von Rechnern! Kilometer über Kilometer Kabel rund um die Welt. Auf einer Webseite über Unterseekabel (http://submarinecablemap.com/) kannst du dir ein Bild von der Komplexität des Netzes machen. Hier ist ein Screenshot der Seite: ![Abbildung 1.2](images/internet_3.png) -Faszinierend, oder? Offensichtlich ist es nicht möglich, Kabel zwischen allen Servern des Internet zu schalten. Um den Server, auf dem z.B. https://djangogirls.org gespeichert ist, zu erreichen, muss unsere Anfrage sehr viele andere Maschinen passieren. +Faszinierend, oder? Offensichtlich ist es nicht möglich, Kabel zwischen allen Servern des Internet zu schalten. 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. Das sieht ungefähr so aus: ![Abbildung 1.3](images/internet_2.png) -Stell dir vor, wenn du https://djangogirls.org in den Browser eingibst, würdest du einen Brief versenden, in dem steht; "Hallo Django Girls, ich möchte die djangogirls.org Webseite ansehen. Bitte schickt sie mir!" +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!" Der Brief kommt ins Postamt in deiner Nähe. Von da aus kommt der Brief zu einem anderen Postamt näher an der Zieladresse und näher und näher, bis der Brief zugestellt werden kann. Die einzigartige Sache ist, dass wenn du mehrere Briefe zu der selben Adresse abschickst (*Datenpakete*), jeder einzelne durch komplett unterschiedliche Poststellen laufen könnte (*Router*). Dies hängt davon ab, wie sie an jedem Standort verteilt werden. ![Abbildung 1.4](images/internet_4.png) -So einfach ist das im Prinzip. Du sendest Nachrichten und erwartest eine Antwort. Anstelle von Papier und Stift verwendest du Daten (Byte für Byte), aber die Idee ist dieselbe. - -Anstelle von Adressen mit Straße, Ort und Postleitzahl verwenden wir IP-Adressen. IP steht für Internet Protocol. Ein Protokoll kann man mit einer Vereinbarung vergleichen, darin wird festgelegt, wie etwas funktionieren soll, ein allgemein gültiger Standard also. Im Internet Protocol steht zum Beispiel auch, wie eine IP-Adresse aufgebaut werden muss. +That's how it works - 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! -Um die von Menschen besser lesbare Adresse "djangogirls.org" in eine IP-Adresse, die von Maschinen besser lesbar ist, umzuwandeln, fragt dein Computer das DNS (Domain Name System). Das DNS ist ein bisschen wie ein altmodisches Telefonbuch aus Papier, in dem du zu einem bestimmten Namen Telefonnummer und Adresse nachgucken kannst. +Anstelle von Adressen mit Straße, Ort und Postleitzahl verwenden wir IP-Adressen. IP steht für Internet Protocol. Dein Computer fragt erst das DNS (Domain Name System), um die (von Menschen besser lesbare) Adresse djangogirls.org in die (besser von Maschinen lesbare) IP-Adresse umzuwandeln. 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. -Wenn du einen Brief versenden willst, brauchst du spezielle Dinge wie: Postanschrift, Briefmarke etc. Außerdem musst du eine Sprache verwenden, die der Empfänger versteht, logisch. Das gleiche gilt auch für die *Datenpakete*, die du sendest, um eine Website betrachten zu können. Wir verwenden einen vereinbarten Standard, ein Protokoll namens HTTP (Hypertext Transfer Protocol) oder HTTPS (Hypertext Transfer Protocol Secure). +When you send a letter, it needs to have certain features to be delivered correctly: an address, a stamp, etc. Außerdem musst du eine Sprache verwenden, die der Empfänger versteht. Das gleiche gilt für die *Datenpakete*, die du sendest, um eine Website betrachten zu können. Wir verwenden ein Protokoll namens HTTP (Hypertext Transfer Protocol). -Grundsätzlich brauchst du also für eine Website auch einen *Server*, auf dem sie abgelegt ist. Wenn der *Server* eine eingehende *Anforderung (Request)* (in einem Brief) empfängt, sendet er deine Website zurück (in einem weiteren Brief). +Grundsätzlich brauchst du also für eine Website auch einen *Server*, auf dem sie abgelegt ist. Wenn der *Server* eine eingehende *Anforderung* (in einem Brief) empfängt, sendet er deine Website zurück (in einem weiteren Brief). -Da dies hier ein Django-Tutorial ist, fragst du dich sicher, was Django in diesem Zusammenhang macht!? Wenn du (bzw. dein Webserver) eine Antwort zurück sendest, willst du nicht an jeden dasselbe senden. Es ist besser, wenn die Antworten individuell personalisiert sind, entsprechend dem an dich gerichteten Anliegen. Django hilft dir, diese personalisierten Antworten zu erstellen. +Since this is a Django tutorial, you might ask what Django does. Wenn du (bzw. dein Webserver) eine Antwort zurück sendest, willst du nicht an jeden dasselbe senden. Es ist besser, wenn die Antworten individuell personalisiert sind, entsprechend dem an dich gerichteten Anliegen. Django helps you with creating these personalized, interesting letters. :) -Genug der Theorie, lass uns loslegen! +Enough talk – time to create! \ No newline at end of file diff --git a/de/html/README.md b/de/html/README.md index 382ec828e8c..26a4a0e66e6 100644 --- a/de/html/README.md +++ b/de/html/README.md @@ -2,15 +2,15 @@ Vielleicht fragst du dich, was ein Template (Vorlage) ist? -Ein Template (zu deutsch "Vorlage") ist eine Textdatei und ermöglicht es uns, verschiedene Inhalte in einer einheitlichen Darstellung zu erzeugen. Eine Vorlage für z.B. einen Brief hilft uns, immer gleich aussehende Nachrichten zu versenden, in denen sich Empfänger, Betreff und Text jeweils ändern, das äußere Format jedoch bestehen bleibt. +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. -Ein Django-Template wird mit einer Sprache namens HTML beschrieben. (Genau das HTML aus dem ersten Kapitel: **Wie das Internet funktioniert**). +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**). ## Was ist HTML? -HTML ist recht einfacher Code, der von deinem Browser - z.B. Chrome, Firefox oder Safari - interpretiert wird, um dem Benutzer eine Website darzustellen. +HTML is a code that is interpreted by your web browser – such as Chrome, Firefox or Safari – to display a web page for the user. -HTML bedeutet "HyperText Markup Language". Als **HyperText** wird Text bezeichnet, der über markierte Textstellen, den "Hyperlinks" (die umgangssprachlichen "Links") auf andere (meist ebenfalls in HTML geschriebene) Seiten verweist. **Markup** bedeutet, dass wir ein Dokument nehmen und mit Code versehen, um einem Empfänger mitzuteilen (in diesem Fall dem Browser), wie diese Seite interpretiert werden muss. HTML-Code besteht aus **Tags**. Jeder Tag startet mit `<` und endet mit `>`. Diese Tags stellen die Markup-**Elemente** dar. +HTML bedeutet "HyperText Markup Language". Als **HyperText** wird Text bezeichnet, der über markierte Textstellen, den "Hyperlinks" (die umgangssprachlichen "Links") auf andere (meist ebenfalls in HTML geschriebene) Seiten verweist. **Markup** bedeutet, dass wir ein Dokument nehmen und mit Code versehen, um einem Empfänger mitzuteilen (in diesem Fall dem Browser), wie diese Seite interpretiert werden muss. HTML-Code besteht aus **Tags**, wovon jeder mit `<` beginnt und mit `>` endet. Diese Tags stellen die Markup-**Elemente** dar. ## Dein erstes Template! @@ -18,19 +18,18 @@ Ein Template zu erstellen, heißt, eine entsprechende Datei dafür zu erstellen. Templates werden im Verzeichnis `blog/templates/blog` gespeichert. Als Erstes erzeugen wir das Verzeichnis `templates` in deinem Blog-Verzeichnis. Im Template-Verzeichnis selbst erstellen wir ein weiteres Verzeichnis `blog`: -``` -blog -└───templates - └───blog -``` + blog + └───templates + └───blog + -(Falls du dich wunderst, warum wir zwei `blog`-Verzeichnisse brauchen - das hängt mit den nützlichen Namenskonventionen von Django zusammen, die das Leben einfacher machen, wenn deine Projekte immer komplizierter und komplexer werden.) +(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.) Als nächstes erstellen wir eine Datei `post_list.html` (erst mal ohne Inhalt) innerhalb des Verzeichnisses `blog/templates/blog`. Kontrolliere deine überarbeitete Webseite unter: http://127.0.0.1:8000 -> Falls du die Fehlermeldung `TemplateDoesNotExists` angezeigt bekommst, versuche den Server neu zu starten. Öffne die Konsole, stoppe den Server mit Strg+C (Steuerung and C Tasten zusammen drücken) und starte ihn neu mit dem `python manage.py runserver` Kommando. +> 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 keys together) and start it again by running a `python manage.py runserver` command. ![Abbildung 11.1](images/step1.png) @@ -38,6 +37,8 @@ Der Fehler sollte weg sein! Toll :) Deine Webseite ist allerdings noch leer, wei Füge folgenden Text in deine Template-Datei ein: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html

Hi there!

@@ -45,16 +46,16 @@ Füge folgenden Text in deine Template-Datei ein: ``` -Hat sich die Seite geändert? Sieh nach: http://127.0.0.1:8000/ +So how does your website look now? Visit it to find out: http://127.0.0.1:8000/ ![Abbildung 11.2](images/step3.png) Es funktioniert! Gute Arbeit! :) -* Jede Webseite sollte mit dem Tag `` beginnen. Und `` steht immer am Ende. Zwischen den beiden Tags `` und `` steht der gesamte Inhalt der Webseite +* The most basic tag, ``, is always the beginning of any web page and `` is always the end. Zwischen den beiden Tags `` und `` steht der gesamte Inhalt der Webseite * `

` ist der Tag für ein Absatz-Element (paragraph), `

` beendet einen Absatz -## Head & body +## Head and body Jede HTML Seite gliedert sich in zwei Teile: **head** und **body**. @@ -64,7 +65,9 @@ Jede HTML Seite gliedert sich in zwei Teile: **head** und **body**. Im `` informieren wir den Browser über Einstellungen und Konfigurationen der Webseite, z.B. wie sie dargestellt werden soll, und im `` darüber, was tatsächlich dargestellt werden soll. -In den `` können wir z.B. noch den Titel (title) der Seite mit aufnehmen: +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 +89,30 @@ Der Titel "Ola's blog" wird nun im Browser angezeigt. Hast du es bemerkt? Der Br Wie du vielleicht bemerkt hast, hat jedes Element zu Beginn einen öffnenden Tag und einen zugehörigen *schließenden Tag* mit `/` und die Elemente sind darin *eingebettet*. Ein Tag in einem zweiten kann nicht außerhalb von diesem geschlossen werden, die Reihenfolge muss immer stimmen. -Es ist wie Sachen in Kisten stecken. In die größte Box: `` kommt eine kleinere Box: ``, und dort wiederum packen wir viele kleine Kisten hinein: `

`. +Es ist wie Sachen in Kisten stecken. In die größte Box: `` kommt eine kleinere Box: ``, und dort wiederum packen wir viele kleine Kisten hinein:
`<p></p>.

+ +

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.

-Die Regeln und Reihenfolgen von _schließenden_ Tags und _Verschachtelung_ der Elemente musst du immer einhalten. Anderenfalls können Browser die Seite nicht richtig interpretieren und darstellen. +

Dein Template anpassen

-## Dein Template anpassen +

Jetzt kannst du ein bisschen rumprobieren und dein Template umgestalten! Hier sind ein paar nützliche Tags dafür:

-Jetzt kannst du ein bisschen rumprobieren und dein Template umgestalten! Hier sind ein paar nützliche Tags dafür: +
    +
  • A heading

    ` for your most important heading
  • -* `

    Überschrift

    ` - (headline) für wichtigste Überschriften * `

    Unter-Überschrift

    ` die nächst tiefere Überschiftenebene -* `

    Unter-Unter-Überschrift

    ` ... und so weiter bis `
    ` +* `

    A sub-sub-heading

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

    A paragraph of text

    ` * `Text` hebt deinen Text hervor * `Text` macht deinen Text fett -* `
    ` fängt eine neue Zeile an (du kannst nichts zwischen br schreiben) -* `link` erstellt einen Link +* `
    ` goes to another line (you can't put anything inside br and there's no closing tag) +* `link` erstellt einen Link * `
    • Erster Punkt
    • second item
    ` generiert eine Liste so wie diese hier! * `
    ` definiert einen Abschnitt auf einer Seite
-Hier ein Beispiel eines vollständigen Templates: + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html @@ -112,36 +121,36 @@ Hier ein Beispiel eines vollständigen Templates:

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.

-
- +        
+ +        
+            

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.

+        
+     ``` Wir haben hier drei verschiedene `div` Abschnitte erstellt. -* Das erste `div` Element enthält den Titel unseres Blogs - eine Überschrift und einen Link +* The first `div` element contains the title of our blog – it's a heading and a link * Zwei weitere `div` Elemente beinhalten unsere Blogposts und ein Publikationsdatum, `h2` mit dem Titel des Posts und zwei `p` (paragraph) Tags mit Text, eines für das Datum und eines für den Blogpost. Wir bekommen das Folgende: ![Abbildung 11.4](images/step6.png) -Yaaay! Bis jetzt zeigt unser Template aber immer genau die **gleichen Inhalte** - obwohl wir aber vorhin davon gesprochen haben, dass Templates uns erlauben, **verschiedene** Informationen im **gleichen Format** darzustellen. +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**. -Eigentlich wollen wir richtige Posts anzeigen, die in unserer Django Admin Oberfläche hinzugefügt wurden - und das wollen wir als Nächstes tun. +What we really want to do is display real posts added in our Django admin – and that's where we're going next. ## Noch eine Sache: Deployment! @@ -151,53 +160,56 @@ Es wäre gut, das alles live draußen im Internet zu sehen, oder? Lass uns noch Lass uns nachsehen, welche Dateien sich nach dem letzten Veröffentlichen (Deployment) geändert haben. (Führe diese Befehle lokal aus und nicht auf PythonAnywhere): -```bash -$ git status -``` +{% filename %}command-line{% endfilename %} + + $ git status + Überprüfe, ob du im `Djangogirls` Verzeichnis bist und sag `git`, dass alle Änderungen in diesem Verzeichnis hinzugefügt werden sollen: -```bash -$ git add --all . -``` +{% filename %}command-line{% endfilename %} + + $ git add --all . + -> **Beachte:** `-A` (kurz für "all") bedeutet, dass `git` auch Dateien berücksichtigt, die du gelöscht hast (in der Standardeinstellung werden nur neue/geänderte Dateien hinzugefügt). Denk auch daran (Kapitel 3), dass `.` das aktuelle Verzeichnis meint. +> **Note** `--all` means that `git` will also recognize if you've deleted files (by default, it only recognizes new/modified files). Denk auch daran (Kapitel 3), dass `.` das aktuelle Verzeichnis meint. Bevor wir alle Dateien hochladen prüfen wir noch einmal, was `git` hochladen will (alle Dateien, die `git` hochladen wird, sind jetzt grün): -```bash -$ git status -``` +{% filename %}command-line{% endfilename %} + + $ git status + Fast fertig, wir sagen nun noch, dass diese Änderung in der Verlaufsübersicht gespeichert werden soll. Wir erstellen eine "Commit Message", die beschreibt, was wir verändert haben. Du kannst an diesem Punkt hier alles reinschreiben, aber es ist sehr nützlich, etwas zu Sinnvolles einzutragen, damit du dich in Zukunft erinnern kannst, was du geändert hast. -```bash -$ git commit -m "HTML der Site geändert." -``` +{% filename %}command-line{% endfilename %} + + $ git commit -m "HTML der Site geändert." + > **Beachte:** Du musst Anführungszeichen um den Commit-Kommentar setzen. -Nachdem wir das gemacht haben, laden (push) wir unsere Änderungen auf GitHub: +Once we've done that, we upload (push) our changes up to GitHub: -```bash -$ git push -``` +{% filename %}command-line{% endfilename %} + + $ git push + ### Hol dir den neuen Code auf PythonAnywhere und aktualisiere deinen Browser * Öffne die [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) und gehe zu deiner **Bash-Konsole** (oder starte eine neue). Dann, führe Folgendes aus: -```bash -$ cd ~/my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic -[...] -```bash +{% filename %}command-line{% endfilename %} + + $ cd ~/my-first-blog + $ git pull + [...] + Schau zu, wie dein Code runtergeladen wird! Wenn du prüfen willst, ob der Code angekommen ist, kannst du zum **Files Tab** rüberspringen und deinen Code auf PythonAnywhere sehen. * Spring anschließend rüber zum [Web Tab](https://www.pythonanywhere.com/web_app_setup/) und klick auf **Neu laden** in deinem Browser. -Dein Update sollte live sein! Lade die Seite neu in deinem Browser. Es sollten nun Änderungen zu sehen sein. :) +Your update should be live! Go ahead and refresh your website in the browser. Changes should be visible. :) \ No newline at end of file diff --git a/de/install_git.md b/de/install_git.md new file mode 100644 index 00000000000..1532e55778e --- /dev/null +++ b/de/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Git installieren + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/de/installation/README.md b/de/installation/README.md index dd0a0958e48..c37c66a4893 100644 --- a/de/installation/README.md +++ b/de/installation/README.md @@ -1,10 +1,10 @@ # Wenn Du dieses Tutorial zu Hause bearbeitest -Wenn Du dieses Tutorial zu Hause bearbeitest, und nicht auf einer der ["Django Girls"-Veranstaltungen](http://djangogirls.org/events/), kannst du dieses Kapitel komplett überspringen und gleich zum Kapitel [Wie funktioniert das Internet?](../how_the_internet_works/README.md) gehen. +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. -Wir werden die folgenden Punkte so oder so im vollständigen Tutorial betrachten. Das hier ist nur eine zusätzliche Seite, die alle Installationsanleitungen an einem Ort bündelt. Die "Django Girls"-Veranstaltung enthält einen "Installationsabend", an dem wir alles installeren, damit wir uns während des Workshops nicht damit beschäftigen müssen. Diese Seite ist für uns daher sehr hilfreich. +Wir werden die folgenden Punkte so oder so im vollständigen Tutorial betrachten. Das hier ist nur eine zusätzliche Seite, die alle Installationsanleitungen an einem Ort bündelt. 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. -Wenn es Dir sinnvoll erscheint, kannst du dieses Kapitel natürlich auch bearbeiten. Wenn Du jedoch mit dem Lernen beginnen willst, bevor du eine handvoll Sachen auf deinem Computer installierst, überspringe dieses Kapitel und lies unsere Erklärungen zur Installation später im Tutorial. +If you find it useful, you can follow 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. Viel Erfolg! @@ -12,38 +12,47 @@ Viel Erfolg! Im Workshop wirst Du einen Blog erstellen und es gibt einige Dinge, bei denen es besser ist, wenn Du sie vorher vorbereitest, so dass Du gleich mit dem Programmieren loslegen kannst. -## Python installieren + {% include "/chromebook_setup/instructions.md" %} + + + +# Python installieren {% include "/python_installation/instructions.md" %} -## Virtualenv einrichten und Django installieren +# Virtualenv einrichten und Django installieren {% include "/django_installation/instructions.md" %} -## Einen Code Editor installieren +# Einen Code Editor installieren -{% include "/code_editor/instructions.md" %} +{% include "code_editor/instructions.md" %} -## Git installieren +# Git installieren -{% include "/code_editor/instructions.md" %} +{% include "/deploy/install_git.md" %} -## Einen GitHub-Account einrichten +# Einen GitHub-Account einrichten -Öffne [GitHub.com](http://www.github.com) und richte Dir einen neuen, kostenfreien Nutzeraccount ein. +Gehe auf [GitHub.com](https://www.github.com) eröffne ein neues, kostenloses Konto. -## Einen PythonAnywhere-Account erstellen +# Einen PythonAnywhere-Account erstellen {% include "/deploy/signup_pythonanywhere.md" %} -## Fang an zu lesen! +# Fang an zu lesen! + +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: + +* [Wie funktioniert das Internet?](../how_the_internet_works/README.md) -Herzlichen Glückwunsch, Du hast alles eingerichtet und bist nun bereit, loszulegen. Wenn Du vor dem Workshop noch etwas Zeit hast, wäre es hilfreich, einige der einführenden Kapitel zu lesen: +* [Einführung in die Kommandozeile](../intro_to_command_line/README.md) - * [Wie funktioniert das Internet?](../how_the_internet_works/README.md) +* [Einführung in Python](../python_introduction/README.md) - * [Einführung in die Kommandozeile](../intro_to_command_line/README.md) +* [Django - Was ist das?](../django/README.md) - * [Einführung in Python](../intro_to_command_line/README.md) +# Enjoy the workshop! - * [Was ist Django?](../django/README.md) +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. \ No newline at end of file diff --git a/de/instructions.md b/de/instructions.md new file mode 100644 index 00000000000..207e154185c --- /dev/null +++ b/de/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Runteraden der *Mac OS X 64-bit/32-bit installer*-Datei, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/de/intro_to_command_line/README.md b/de/intro_to_command_line/README.md index b009c41245b..6d14c8bbe6f 100644 --- a/de/intro_to_command_line/README.md +++ b/de/intro_to_command_line/README.md @@ -1,77 +1,110 @@ # Einführung in die Kommandozeile -Uuh, aufregend, oder?! In ein paar Minuten wirst du deine erste Zeile Code schreiben :) +> 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! :) **Erstmal stellen wir dir deine neue Freundin vor: Die Konsole!** Im Folgenden zeigen wir dir, wie du das schwarze Fenster benutzt, das alle Hackerinnen nutzen. Es sieht vielleicht erstmal etwas unheimlich aus, aber es ist nur ein Programm, das darauf wartet, Anweisungen von dir zu bekommen. -> **Hinweis:** Bitte beachte, dass wir in dem gesamten Buch die Begriffe "Verzeichnis" und "Ordner" abwechselnd gebrauchen, aber sie stehen für ein und dasselbe. +> **Note** Please note that throughout this book we use the terms 'directory' and 'folder' interchangeably but they are one and the same thing. ## Was ist die Konsole? -Das Fenster, welches gewöhnlich die **Kommandokonsole** (command line) oder **Kommandoleisten-Interface** (command-line interface) genannt wird, ist eine textbasierte Applikation zum Betrachten, Bearbeiten und Manipulieren von Dateien auf deinem Computer. Ähnlich wie der Windows Explorer oder der Finder auf dem Mac, aber ohne die grafische Benutzeroberfläche. Andere Bezeichnungen dafür sind: cmd, CLI, prompt, Eingabeaufforderung, Kommandozeile, Konsole, Terminal. +Das Fenster, welches gewöhnlich die **Kommandokonsole** (command line) oder **Kommandoleisten-Interface** (command-line interface) genannt wird, ist eine textbasierte Applikation zum Betrachten, Bearbeiten und Manipulieren von Dateien auf deinem Computer. It's much like Windows Explorer or Finder on the Mac, but without the graphical interface. Andere Bezeichnungen dafür sind: cmd, CLI, prompt, Eingabeaufforderung, Kommandozeile, Konsole, Terminal. ## Öffnen der Konsole Um mit unserem Tutorial zu starten, musst du als Erstes das Kommandozeilenprogramm starten. -### Windows + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. -Geh ins Start Menü → Alle Programme → Zubehör → Eingabeaufforderung. + -### Mac OS X + -Programme → Zubehör → Terminal. +Go to Applications → Utilities → Terminal. -### Linux + -Wahrscheinlich ist es unter Programme → Zubehör → Terminal, aber das ist von deinem System abhängig. Wenn es nicht da ist, google einfach schnell danach :) + + +Wahrscheinlich ist es unter Programme → Zubehör → Terminal, aber das ist von deinem System abhängig. Wenn es nicht da ist, google einfach schnell danach. :) + + ## Eingabeaufforderung (Prompt) Du solltest nun ein weißes oder schwarzes Fenster sehen, das auf deine Anweisungen wartet. + + Auf einem Mac oder Linux, siehst du wahrscheinlich `$`, also so: -```bash -$ -``` +{% filename %}command-line{% endfilename %} + + $ + + + + + Auf Windows siehst du ein `>` Zeichen, also das hier: -```bash -> -``` +{% filename %}command-line{% endfilename %} + + > + + + -Vor jedem Kommando wird dieses Zeichen und ein Leerzeichen vorangestellt, aber du musst das nicht hinschreiben. Dein Computer macht das für dich :) +Vor jedem Kommando wird dieses Zeichen und ein Leerzeichen vorangestellt, aber du musst das nicht hinschreiben. Dein Computer macht das für dich. :) -> Ein kleiner Hinweis: Falls du etwas in der Art wie `C:\Users\ola>` oder `Olas-MacBook-Air:~ ola$` sehen solltest, ist das auch 100%ig korrekt. In diesem Tutorial werden wir das Ganze auf das einfachste Minimum herunterbrechen. +> 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. ## Dein erstes Kommando (YAY!) -Fangen wir mit etwas Einfachem an. Schreibe folgenden Befehl: +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + -```bash -$ whoami -``` + -oder + -```bash -> whoami -``` +{% filename %}command-line{% endfilename %} + + > whoami + + + Und dann betätige mit `Enter`. Das ist unser Ergebnis: -```bash -$ whoami -olasitarska -``` +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + -Wie du sehen kannst, hat der Computer gerade deinen Benutzernamen ausgegeben. Toll, was? :) +As you can see, the computer has just printed your username. Neat, huh? :) -> Versuch, jeden Befehl abzuschreiben und nicht zu kopieren und einzufügen. Auf diese Weise wirst du dir mehr merken! +> Try to type each command; do not copy-paste. You'll remember more this way! ## Grundlagen @@ -81,194 +114,293 @@ Jedes Betriebssystem hat einen geringfügig anderen Bestand an Befehlen für die Es wäre schön zu sehen, wo wir uns befinden, oder? Lass uns nachsehen. Gib diesen Befehl in die Konsole ein und bestätige ihn mit `Enter`: -```bash -$ pwd -/Users/olasitarska -``` + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + -Wenn du Windows benutzt, schreibe Folgendes: +> Hinweis: 'pwd' steht für 'print working directory' (zeige derzeitiges Arbeitsverzeichnis). + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. -```bash -> cd -C:\Users\olasitarska -``` + Du wirst wahrscheinlich etwas Ähnliches auf deinem Gerät sehen. Wenn du die Konsole öffnest, befindest du dich normalerweise im Heimverzeichnis deines Benutzers. -> Hinweis: 'pwd' steht für 'print working directory' (zeige derzeitiges Arbeitsverzeichnis). +* * * ### Anzeigen von Dateien und Unterordnern Nun, was befindet sich in deinem Verzeichnis? Es wäre toll, das herauszufinden. Lass uns mal schauen: -```bash -$ ls -Anwendungen -Desktop -Downloads -Musik -... -``` - -Windows: - -```bash -> 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 + Anwendungen + Desktop + Downloads + Musik + ... + + + + + + +{% 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 ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * ### Wechseln des Verzeichnisses Lass uns jetzt zu unserem Desktop-Verzeichnis wechseln: -```bash -$ cd Desktop -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ cd Desktop + -```bash -> cd Desktop -``` + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + Schau, ob das Wechseln des Verzeichnisses funktioniert hat: -```bash -$ pwd -/Users/olasitarska/Desktop -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ pwd + /Users/olasitarska/Desktop + -```bash -> cd -C:\Users\olasitarska\Desktop -``` + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + Hier ist es! -> Profi-Tipp: Wenn du `cd D` tippst und dann `tab` auf deiner Tastatur drückst, wird die Kommandozeile automatisch den Rest des Namens vervollständigen, wodurch du schneller navigieren kannst. Wenn es mehr als einen Ordner gibt, dessen Name mit "D" beginnt, drücke die `tab`-Taste zweimal, um eine Liste der Möglichkeiten anzuzeigen. +> 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` key twice to get a list of options. + +* * * ### Erstellen eines Verzeichnisses Wie wärs damit, ein Probeverzeichnis auf deinem Desktop zu erstellen? So kannst du das tun: -```bash -$ mkdir practice -``` + + +{% filename %}command-line{% endfilename %} -Windows: + $ mkdir practice + -```bash -> mkdir practice -``` + -Dieser kleine Befehl erstellt einen Ordner mit dem Namen `practice` auf deinem Desktop. Du kannst nun überprüfen, ob er wirklich dort ist, indem du auf deinem Desktop nachschaust oder indem du den Befehl `ls` oder `dir` ausführst! Versuch es :) + + +{% filename %}command-line{% endfilename %} + + > mkdir practice + + + + +Dieser kleine Befehl erstellt einen Ordner mit dem Namen `practice` auf deinem Desktop. Du kannst nun überprüfen, ob er wirklich dort ist, indem du auf deinem Desktop nachschaust oder indem du den Befehl `ls` oder `dir` ausführst! Versuch es. :) > Profi-Tipp: Wenn du die selben Befehle nicht immer wieder und wieder schreiben willst, verwende die `Pfeil aufwärts`- und `Pfeil abwärts`-Tasten deiner Tastatur, um durch die zuletzt verwendeten Befehle zu blättern. +* * * + ### Übung! -Eine kleine Herausforderung für dich: Erstelle in deinem neu erstellten `practice`-Ordner ein Verzeichnis namens `test`. Verwende dazu die `cd` und `mkdir`-Kommandos. +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) #### Lösung: -```bash -$ cd practice -$ mkdir test -$ ls test -``` + -Windows: +{% filename %}command-line{% endfilename %} -```bash -> cd practice -> mkdir test -> dir -05/08/2014 07:28 PM test -``` + $ cd practice + $ mkdir test + $ ls test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + Glückwunsch! :) +* * * + ### Aufräumen Wir wollen kein Chaos hinterlassen, also lass uns das bislang Geschaffene wieder löschen. Zuerst müssen wir zurück zum Desktop wechseln: -```bash -$ cd .. -``` + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + -Windows: +{% filename %}command-line{% endfilename %} -```bash -> cd .. -``` + > cd .. + -Durch Verwendung von `..` mit dem `cd` Kommando wechselst du von deinem aktuellen Verzeichnis zum übergeordneten Verzeichnis (dies ist das Verzeichnis, das das aktuelle Verzeichnis enthält). + + +Using `..` with the `cd` command will change your current directory to the parent directory (that is, the directory that contains your current directory). Schau nach, wo du gerade bist: -```bash -$ pwd -/Users/olasitarska/Desktop -``` + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} -Windows: + > cd + C:\Users\olasitarska\Desktop + -```bash -> cd -C:\Users\olasitarska\Desktop -``` + Jetzt ist es an der Zeit, dein `practice`-Verzeichnis zu löschen: -> **Achtung**: Wenn du Daten mit `del`, `rmdir` oder `rm` löschst, kannst du das nicht mehr rückgängig machen, das bedeutet *die gelöschten Dateien sind für immer weg*! Sei also sehr vorsichtig mit diesem Befehl. +> **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. + + + +{% filename %}command-line{% endfilename %} -```bash $ rm -r practice -``` + + + + + + +{% filename %}command-line{% endfilename %} -Windows: + > rmdir /S practice + practice, Are you sure ? Y + -```bash -> rmdir /S practice -practice, Are you sure ? Y -``` + Geschafft! Lass uns schauen, ob es wirklich gelöscht ist: -```bash -$ ls -``` + -Windows: +{% filename %}command-line{% endfilename %} -```bash -> dir -``` + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + ### Beenden -Das wärs fürs Erste. Du kannst nun beruhigt deine Konsole schließen. Lass es uns wie die Hacker machen, okay? :) +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 + + + + + -```bash -$ exit -``` +{% filename %}command-line{% endfilename %} -Windows: + > exit + -```bash -> exit -``` + -Cool, was? :) +Cool, huh? :) ## Zusammenfassung @@ -276,18 +408,20 @@ Hier ist eine Zusammenfassung einiger nützlicher Kommandos: | Befehl (Windows) | Befehl (Mac OS / Linux) | Beschreibung | Beispiel | | ---------------- | ----------------------- | --------------------------- | ------------------------------------------------- | -| exit | exit | Fenster schließen | **exit** | +| beenden | beenden | Fenster schließen | **beenden** | | cd | cd | Verzeichnis wechseln | **cd test** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | | dir | ls | Unterordner/Dateien zeigen | **dir** | | copy | cp | Datei kopieren | **copy c:\test\test.txt c:\windows\test.txt** | | move | mv | Datei verschieben | **move c:\test\test.txt c:\windows\test.txt** | | mkdir | mkdir | neues Verzeichnis erstellen | **mkdir testdirectory** | -| del | rm | Ordner/eine Datei löschen | **del c:\test\test.txt** | +| rmdir (or del) | rm | delete a file | **del c:\test\test.txt** | +| rmdir /S | rm -r | delete a directory | **rm -r testdirectory** | Das sind nur sehr wenige aller Befehle, die du in deiner Konsole verwenden kannst, heute aber wirst du keine weiteren brauchen. -Falls du neugierig bist, findest du auf [ss64.com](http://ss64.com) eine vollständige Übersicht über alle Kommandozeilen-Befehle für alle Betriebssysteme. +Falls du neugierig bist, findest du auf [ss64.com](http://ss64.com) eine vollständige Übersicht über alle Kommandozeilen-Befehle für alle Betriebssysteme. ## Fertig? -Lass uns mit Python anfangen! +Lass uns mit Python anfangen! \ No newline at end of file diff --git a/de/python_installation/README.md b/de/python_installation/README.md index aa4bdaf4d4f..aea48342251 100644 --- a/de/python_installation/README.md +++ b/de/python_installation/README.md @@ -4,10 +4,12 @@ Wir sind endlich da! Aber lass uns zuerst erklären, was Python ist. Python ist eine sehr beliebte Programmiersprache, die du zur Erstellung von Webseiten, Spielen, wissenschaftlichen Programmen, Computergrafiken und vielem, vielem mehr verwenden kannst. -Python entstand in den späten 1980ern mit dem Hauptziel, von Menschen lesbar zu sein (nicht nur von Computern). Darum sieht es auch um Längen einfacher als andere Programmmiersprachen aus. Daher ist es einfach, Python zu lernen, aber keine Sorge, Python ist auch sehr mächtig! +Python entstand in den späten 1980ern mit dem Hauptziel, von Menschen lesbar zu sein (nicht nur von Computern). This is why it looks simpler than other programming languages, but don't worry – Python is also really powerful! # Python-Installation -> **Hinweis:** Falls du dich bereits durch die Installationsschritte gearbeitet hast, gibt es keinen Grund dies erneut zu tun - du kannst direkt zum nächsten Kapitel springen! +> **Hinweis** Wenn du ein Chromebook verwendest, überspringe bitte dieses Kapitel und folge den Anweisungen im [Chromebook Setup](../chromebook_setup/README.md). +> +> **Hinweis:** Wenn du die Installation bereits hinter dir hast, gibt es keinen Grund dies erneut zu tun - du kannst direkt zum nächsten Kapitel springen! -{% include "/python_installation/instructions.md" %} +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/de/python_installation/instructions.md b/de/python_installation/instructions.md index c52ba5a0825..fd091d317c2 100644 --- a/de/python_installation/instructions.md +++ b/de/python_installation/instructions.md @@ -1,62 +1,106 @@ -> Dieses Unterkapital basiert auf einem Tutorial der Geek Girls Carrots (http://django.carrots.pl/). +> 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 ist in Python geschrieben. Wir brauchen Python für alles in Django. Fangen wir mit der Installation an! Wir möchten, dass du Python 3.5 installierst, solltest du also bereits eine ältere Version installiert haben, musst du diese aktualisieren. +Django ist in Python geschrieben. Um mit Django zu arbeiten müssen wir also erst Python installieren. Lass uns also zunächst Python installieren! Für das Tutorial brauchen wir Python 3.6, falls du eine Vorgängerversion benutzt upgrade diese bitte. -### Windows + -Python für Windows kannst du auf der Webseite https://www.python.org/downloads/windows/ herunterladen. Nachdem du die ***.msi**-Datei heruntergeladen hast, solltest du diese ausführen (doppelklicke die Datei) und den Anweisungen folgen. Es ist wichtig, dass du dir den Pfad (das Verzeichnis) merkst, wo du Python installierst. Du wirst das später brauchen! +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. Python für Windows kannst du auf der Webseite https://www.python.org/downloads/release/python-343/ herunterladen. Klicke auf den "Latest Python 3 Release - Python x.x.x" Link. Wenn du eine **64-bit** Version von Windows benutzt, downloade die Datei **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. -Worauf du besonders achten solltest: im zweiten Schritt des Installationsassistenten ("Anpassen") solltest du nach unten scrollen und die Option "Add python.exe to the Path" auswählen, wie hier: +One thing to watch out for: During the installation, you will notice a window marked "Setup". Make sure you tick the "Add Python 3.6 to PATH" checkbox and click on "Install Now", as shown here: -![Vergiss nicht, Python zu dem Pfad hinzuzufügen](../python_installation/images/add_python_to_windows_path.png) +![Vergiss nicht, Python zu dem Pfad hinzuzufügen](../python_installation/images/python-installation-options.png) -### Linux +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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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." + +Auf der Website https://www.python.org/downloads/release/python-361/ findest du den passenden Python-Installer: + +* Runteraden der *Mac OS X 64-bit/32-bit installer*-Datei, +* Doppelklicke auf *Python.mpkg* um die Installation zu starten. + + + + Es ist ziemlich wahrscheinlich, dass du Python schon automatisch installiert hast. Um herauszufinden, ob das so ist (und wenn ja, welche Version du hast), öffne eine Konsole und gib das folgende Kommando ein: -```bash -$ python3 --version -Python 3.5.1 -``` +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.0, then you don't have to upgrade. Wenn Python bei dir nicht installiert ist, oder du eine andere Version willst, kannst du es folgendermaßen installieren: -Wenn Python bei dir nicht installiert ist, oder du eine andere Version willst, kannst du es folgendermaßen installieren: + -#### Debian oder Ubuntu + Gib diesen Befehl in die Konsole ein: -```bash -$ sudo apt-get install python3.5 -``` +{% filename %}command-line{% endfilename %} + + $ sudo apt-get install python3.6 + + + -#### Fedora (bis zu 21) + Gib diesen Befehl in die Konsole ein: -```bash - $ sudo yum install python3.5 -``` +{% filename %}command-line{% endfilename %} -#### Fedora (22+) + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + Gib diesen Befehl in die Konsole ein: -```bash -$ sudo dnf install python3.5 -``` +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + -### OS X +Verify the installation was successful by opening a command prompt and running the `python3` command: -Auf der Website https://www.python.org/downloads/release/python-343/ findest du den passenden Python-Installer: +{% filename %}command-line{% endfilename %} - * Runteraden der *Mac OS X 64-bit/32-bit installer*-Datei, - * Doppelklick auf *python-3.5.1-macosx10.6.pkg*, um das Installationsprogramm auszuführen. + $ python3 --version + Python 3.6.1 + -Um zu überprüfen, ob die Installation erfolgreich war, öffne eine Konsole und gib das `python3`-Kommando ein: +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. -```bash -$ python3 --version -Python 3.5.1 -``` +* * * -Falls du irgendwelche Zweifel hast oder falls etwas falsch gelaufen ist und du keine Ahnung hast, was als Nächstes zu tun ist - frag einfach deinen Coach! Manchmal laufen die Dinge einfach nicht so glatt und dann ist es besser, jemanden mit mehr Erfahrung zu fragen. +If you have any doubts, or if something went wrong and you have no idea what to do next, please ask your coach! Manchmal laufen die Dinge einfach nicht so glatt und dann ist es besser, jemanden mit mehr Erfahrung zu fragen. \ No newline at end of file diff --git a/de/python_introduction/README.md b/de/python_introduction/README.md index 1f6dedd089b..5387b92c33e 100644 --- a/de/python_introduction/README.md +++ b/de/python_introduction/README.md @@ -1,50 +1,65 @@ # Einführung in Python -> Ein Teil dieses Kapitels basiert auf dem Tutorial der Geek Girls Karotten (http://django.carrots.pl/). +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). Fangen wir an, schreiben wir Code! ## Der Python-Prompt -Um Python zu starten, musst du an die *Kommandozeile* deines Computers. Wie das geht, weißt du bereits -- denn du hast es im Kapitel [Einführung in die Kommandozeile](../intro_to_command_line/README.md) gelernt. +> 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. + +Um Python zu starten, musst du an die *Kommandozeile* deines Computers. You should already know how to do that – you learned it in the [Intro to Command Line](../intro_to_command_line/README.md) chapter. Also öffne die Konsole, dann fangen wir an. Wir wollen eine Python Konsole öffnen, also tippe in Windows `python` ein oder in Mac OS/Linux `python3` und drücke `Enter`. -``` -$ python3 -Python 3.5.1 (...) -Type "help", "copyright", "credits" or "license" for more information. ->>> -``` +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.1 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + ## Dein erster Python-Befehl! -Nach Eingabe von python3 in der Konsole ändert sich das Prompt-Zeichen zu `>>>`. Für uns bedeutet das, dass wir ab nun nur noch Python-Code eingeben können. Den Python-Prompt `>>>` musst du nicht jedesmal eingeben - dies macht Python für dich. +Nach Eingabe von python3 in der Konsole ändert sich das Prompt-Zeichen zu `>>>`. Für uns bedeutet das, dass wir ab nun nur noch Python-Code eingeben können. You don't have to type in `>>>` – Python will do that for you. Wenn du die Python-Konsole wieder verlassen möchtest, gib einfach `exit()` ein oder nutze das Tastatur-Kürzel `Strg + Z` unter Windows bzw. `Strg + D`, wenn du einen Mac hast oder Linux verwendest. Dann bist Du wieder in der normalen Konsole und der Python-Prompt `>>>` ist weg. -Aber jetzt wollen wir die Python-Konsole ja noch nicht beenden. Wir wollen mehr darüber erfahren. Fangen wir mit etwas wirklich Einfachem an. Zum Beispiel: Versuch mal etwas Mathematisches einzugeben, wie `2 + 3` und drücke `Enter`. +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% filename %}command-line{% endfilename %} ```python ->>> 2 + 3 +>>> 2 + 3 5 ``` -Cool! Schon ist das Ergebnis da. Python kann rechnen! Probier einfach auch einige andere Befehle aus, wie z.B.: -* `4 * 5` -* `5 - 1` -* `40 / 2` +Nice! See how the answer popped out? Python knows math! You could try other commands like: -Spiel ein wenig herum, dann machen wir weiter :). +- `4 * 5` +- `5 - 1` +- `40 / 2` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` -Wie du siehst, kann Python richtig toll rechnen. Aber Python kann noch viel mehr ... +Spiel ein wenig herum, dann machen wir weiter. :) + +As you can see, Python is a great calculator. If you're wondering what else you can do… ## Strings Strings sind Zeichenketten. Das ist eine Folge von Buchstaben, die von Anführungszeichen umgeben sind. Gib einfach mal deinen Namen ein (bei mir "Ola"): +{% filename %}command-line{% endfilename %} + ```python >>> "Ola" 'Ola' @@ -54,6 +69,8 @@ Nun hast du deinen ersten String erzeugt! Dies ist eine Folge von Zeichen (also Strings können zusammengesetzt werden. Versuch es einmal: +{% filename %}command-line{% endfilename %} + ```python >>> "Hi there " + "Ola" 'Hi there Ola' @@ -61,6 +78,8 @@ Strings können zusammengesetzt werden. Versuch es einmal: Du kannst Strings auch vervielfältigen: +{% filename %}command-line{% endfilename %} + ```python >>> "Ola" * 3 'OlaOlaOla' @@ -70,6 +89,8 @@ Brauchst du ein Apostroph in einem String, so hast du zwei Möglichkeiten. Du kannst für den String doppelte Anführungszeichen verwenden: +{% filename %}command-line{% endfilename %} + ```python >>> "Runnin' down the hill" "Runnin' down the hill" @@ -77,21 +98,27 @@ Du kannst für den String doppelte Anführungszeichen verwenden: oder du kannst den Apostroph mit einem Backslash (``) markieren: +{% filename %}command-line{% endfilename %} + ```python >>> 'Runnin\' down the hill' "Runnin' down the hill" ``` -Toll, was? Um deinen Namen in Großbuchstaben anzuzeigen, gib einfach Folgendes ein: +Toll, was? Um deinen Namen in Großbuchstaben anzuzeigen, gib einfach folgendes ein: + +{% filename %}command-line{% endfilename %} ```python >>> "Ola".upper() 'OLA' ``` -Hier hast du die `upper`-**Funktion** des Strings verwendet! Eine Funktion (wie `upper()`) ist eine Abfolge von Anweisungen, die Python ausführt, wenn die Funktion bei einem gegebenen Objekt (hier `"Ola"`) aufgerufen wird. +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! -Nehmen wir an, du möchtest die Zahl der Buchstaben in deinem Namen wissen. Auch dafür gibt es eine Funktion! +{% filename %}command-line{% endfilename %} ```python >>> len("Ola") @@ -104,10 +131,10 @@ Nun fragst du dich sicher, warum du manchmal eine Funktion mit einem `.` am Ende Ok, genug über Strings. Bisher haben wir Folgendes kennengelernt: -* **Der Prompt** - Wenn wir beim Python-Prompt Anweisungen (oder Programm-Code) in Python eingeben, dann erhalten wir auch Ergebnisse in Python -* **Zahlen und Strings** - In Python nutzen wir Zahlen für Berechnungen und Strings für Text-Objekte -* **Operatoren** - wie + und *, verarbeiten mehrere Werte und erzeugen als Ergebnis einen neuen Wert -* **Funktionen** - wie upper() und len(), tun etwas mit Objekten (in unserem Beispiel ändern sie sie, wie bei upper(), oder geben eine Eigenschaft zurück, wie bei len()). +- **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. Das sind Grundlagen jeder Programmiersprache, die Du lernen wirst. Bist Du bereit für mehr? Bestimmt! @@ -115,6 +142,8 @@ Das sind Grundlagen jeder Programmiersprache, die Du lernen wirst. Bist Du berei Probieren wir etwas Neues: Errors. Können wir die Länge einer Zahl auf die gleiche Weise ermitteln, wie die Länge eines Namens? Gib dazu `len(304023)` ein und drücke auf Enter: +{% filename %}command-line{% endfilename %} + ```python >>> len(304023) Traceback (most recent call last): @@ -124,6 +153,8 @@ TypeError: object of type 'int' has no len() Ha, unser erster Fehler! Dieser sagt, dass Objekte vom Typ "int" (Integers, das sind ganze Zahlen) keine Länge haben. Was also nun? Vielleicht sollten wir unsere Zahl als String schreiben? Denn bei Strings funktioniert es ja, wie wir wissen. +{% filename %}command-line{% endfilename %} + ```python >>> len(str(304023)) 6 @@ -131,10 +162,10 @@ Ha, unser erster Fehler! Dieser sagt, dass Objekte vom Typ "int" (Integers, das Ja, das funktioniert! Hier haben wir die `str`-Funktion innerhalb der `len`-Funktion aufgerufen. `str()` konvertiert alles zu einem String. -* Die `str`-Funktion wandelt den übergebenen Wert in einen **String** um -* Die `int`-Funktion wandelt den übergebenen Wert in einen **Integer** um +- Die `str`-Funktion wandelt den übergebenen Wert in einen **String** um +- Die `int`-Funktion wandelt den übergebenen Wert in einen **Integer** um -> Wichtig: Zwar können wir Zahlen in Text umwandeln, aber nicht immer auch Text in Zahlen - was beispielsweise sollte `int('hello')` ergeben? +> Important: we can convert numbers into text, but we can't necessarily convert text into numbers – what would `int('hello')` be anyway? ## Variablen @@ -142,20 +173,26 @@ Ein wichtiger Bestandteil beim Programmieren sind Variablen. Eine Variable ist e Legen wir eine Variable mit der Bezeichnung `name` an: +{% filename %}command-line{% endfilename %} + ```python >>> name = "Ola" ``` -Das war es schon! Einfach name gleich Ola. +We type name equals Ola. Du hast sicher schon bemerkt, dass Python diesmal kein Ergebnis zurückgegeben hat. Woher sollen wir nun wissen, dass es die Variable jetzt auch tatsächlich gibt? Zum Test geben wir `name` ein und drücken wieder auf Enter: +{% filename %}command-line{% endfilename %} + ```python >>> name 'Ola' ``` -Hurra! Deine erste Variable :)! Nun kannst du auch stets ändern, was sie enthalten soll: +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} ```python >>> name = "Sonja" @@ -165,12 +202,16 @@ Hurra! Deine erste Variable :)! Nun kannst du auch stets ändern, was sie enthal Du kannst sie auch in Funktionen verwenden: +{% filename %}command-line{% endfilename %} + ```python >>> len(name) 5 ``` -Das ist toll, oder? Variable können alles sein, also auch Zahlen. Versuche Folgendes: +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% filename %}command-line{% endfilename %} ```python >>> a = 4 @@ -181,6 +222,8 @@ Das ist toll, oder? Variable können alles sein, also auch Zahlen. Versuche Folg Was aber, wenn wir für eine Variable den falschen Namen verwenden? Uns einfach vertippen. Hast du schon eine leise Ahnung, was dann passiert? Probieren wir es aus! +{% filename %}command-line{% endfilename %} + ```python >>> city = "Tokyo" >>> ctiy @@ -197,6 +240,8 @@ Spiel einfach ein wenig rum und schaue, was alles so passiert. Gib einmal Folgendes ein: +{% filename %}command-line{% endfilename %} + ```python >>> name = 'Maria' >>> name @@ -211,10 +256,12 @@ Wie wir später sehen werden, ist `print()` auch recht nützlich, wenn wir etwas ## Listen -Außer Strings (Zeichenketten) und Integern (ganze Zahlen) hat Python noch einige andere Arten von Daten-Objekten. Von denen wollen wir uns nun **Listen** anschauen. Listen sind genau das, was du wahrscheinlich schon vermutest: Objekte, welche Listen von anderen Objekten enthalten :) +Außer Strings (Zeichenketten) und Integern (ganze Zahlen) hat Python noch einige andere Arten von Daten-Objekten. Von denen wollen wir uns nun **Listen** anschauen. Listen sind genau das, was du wahrscheinlich schon vermutest: Objekte, welche Listen von anderen Objekten enthalten. :) Legen wir los und erzeugen eine Liste: +{% filename %}command-line{% endfilename %} + ```python >>> [] [] @@ -222,12 +269,16 @@ Legen wir los und erzeugen eine Liste: Ja, dies ist eine leere Liste. Für uns noch nicht sehr nützlich. Legen wir nun eine Liste von Lottozahlen an. Da wir uns nicht dauernd wiederholen wollen, ordnen wir diese Liste auch direkt einer Variablen zu: +{% filename %}command-line{% endfilename %} + ```python >>> lottery = [3, 42, 12, 19, 30, 59] ``` So, nun haben wir eine Liste mit Lottozahlen! Was aber können wir damit tun? Zuerst einmal wollen wir feststellen, wie viele Zahlen in ihr enthalten sind. Hast du schon eine Idee, wie dies geht? Klar, das weißt du ja bereits! +{% filename %}command-line{% endfilename %} + ```python >>> len(lottery) 6 @@ -235,12 +286,16 @@ So, nun haben wir eine Liste mit Lottozahlen! Was aber können wir damit tun? Zu Genau! `len()` liefert die Anzahl von Objekten in einer Liste zurück. Praktisch, nicht wahr? Nun wollen wir die Liste sortieren: +{% filename %}command-line{% endfilename %} + ```python >>> lottery.sort() -``` +``` Diese Anweisung gibt nichts zurück. Was passiert, ist, dass die Reihenfolge der Objekte in der Liste geändert werden. Nun wollen wir die Liste ausgeben um nachzusehen, was geschehen ist: +{% filename %}command-line{% endfilename %} + ```python >>> print(lottery) [3, 12, 19, 30, 42, 59] @@ -250,13 +305,17 @@ Wie du siehst, sind die Zahlen in der Liste nun aufsteigend sortiert. Super! Aber vielleicht wollten wir es genau andersherum haben? Nichts leichter als das! +{% filename %}command-line{% endfilename %} + ```python >>> lottery.reverse() >>> print(lottery) [59, 42, 30, 19, 12, 3] ``` -Einfach, oder? Du kannst auch etwas zu deiner Liste hinzufügen: +If you want to add something to your list, you can do this by typing this command: + +{% filename %}command-line{% endfilename %} ```python >>> lottery.append(199) @@ -266,6 +325,8 @@ Einfach, oder? Du kannst auch etwas zu deiner Liste hinzufügen: Falls du nicht immer die gesamte Liste, sondern beispielsweise nur den ersten Eintrag sehen möchtest, kannst du dafür **Indizes** benützen. Ein Index gibt die Stelle innerhalb einer Liste an, die uns interessiert. Programmierer bevorzugen es, bei 0 mit dem Zählen anzufangen. Also hat das erste Objekt in deiner Liste den Index 0, das nächste die 1 und so weiter. Gib einmal Folgendes ein: +{% filename %}command-line{% endfilename %} + ```python >>> print(lottery[0]) 59 @@ -275,7 +336,9 @@ Falls du nicht immer die gesamte Liste, sondern beispielsweise nur den ersten Ei Wie Du siehst, kannst Du auf die einzelnen Objekte in Deiner Liste zugreifen, indem Du den Namen der Liste verwendest und anschließend den Index in eckigen Klammern anfügst. -Um etwas aus deiner Liste zu löschen, musst du **Indizes** und die **del**-Anweisung benutzen, wie wir es weiter oben gelernt haben (del ist eine Abkürzung für delete). Lass uns ein Beispiel versuchen und das festigen, was wir zuvor gelernt haben; wir werden die erste Nummer aus unserer Liste löschen. +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. + +{% filename %}command-line{% endfilename %} ```python >>> print(lottery) @@ -296,7 +359,11 @@ Eine Liste aller Methoden, die du auf Listen anwenden kannst, findest du in der ## Dictionaries -Ein Wörterbuch (von nun an mit dem englischen Begriff 'Dictionary' bezeichnet) verhält sich ähnlich wie eine Liste, jedoch greifen wir auf die enthaltenen Objekte nicht mit einem Index, sondern mit einem Schlüssel zu (auf englisch 'key', und auch hier verwenden wir im weiteren den englischen Begriff). Ein 'key' kann ein String oder eine Zahl sein. Ein leeres Dictionary legen wir wie folgt an: +> 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 >>> {} @@ -305,29 +372,35 @@ Ein Wörterbuch (von nun an mit dem englischen Begriff 'Dictionary' bezeichnet) Und schon hast du ein leeres Dictionary erstellt. Super! -Nun gib einmal Folgendes ein (verwende statt 'Ola' usw. deine eigenen Informationen): +Now, try writing the following command (try substituting your own information, too): + +{% filename %}command-line{% endfilename %} ```python >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} ``` -Du hast nun soeben die Variable mit dem Namen `participant` angelegt, die ein Dictionary mit drei key-value Paaren enthält (values, also Werte - aber auch hier bleiben wir beim englischen Begriff - sind die Objekte in einem Dictionary): +With this command, you just created a variable named `participant` with three key–value pairs: -* Der key `name` verweist auf den value `'Ola'` (welches ein `string` Objekt ist), -* `country` verweist auf `'Poland'` (ebenfalls ein `string` Objekt), -* und `favorite_numbers` schließlich verweist auf `[7, 42, 92]` (eine `Liste` mit drei Zahlen drin). +- Der key `name` verweist auf den value `'Ola'` (welches ein `string` Objekt ist), +- `country` verweist auf `'Poland'` (ebenfalls ein `string` Objekt), +- und `favorite_numbers` schließlich verweist auf `[7, 42, 92]` (eine `Liste` mit drei Zahlen drin). Auf die einzelnen Objekte in einem Dictionary kannst du wie folgt zugreifen: +{% filename %}command-line{% endfilename %} + ```python >>> print(participant['name']) Ola ``` -Also ganz ähnlich wie bei einer Liste. Aber statt dir einen Index merken zu müssen, benutzt du bei einem Dictionary einfach einen Namen (hier: den String 'name'). +See, it's similar to a list. But you don't need to remember the index – just the name. Was aber geschieht, wenn wir Python nach dem Wert eines keys fragen, den es gar nicht gibt? Errätst du es schon? Probieren wir es einfach aus und schauen was passiert! +{% filename %}command-line{% endfilename %} + ```python >>> participant['age'] Traceback (most recent call last): @@ -339,58 +412,71 @@ Ah, wieder ein Fehler! Diesmal ein **KeyError**. Python hilft uns auch hier und Wenn du zwischen Dictionaries und Listen wählen kannst, wann sollte welche Datenstruktur verwendet werden? Das ist eine gute Frage, über die es sich nachzudenken lohnt; und vielleicht möchtest du dies kurz tun, bevor du weiterliest. -* Du brauchst nur eine geordnete Folge von Elementen? Dann wähle eine Liste. -* Du brauchst eine Sammlung von Elementen, auf die du später einzeln, gezielt und effizient mit Hilfe eines Namens (d.h. keys) zugreifen kannst? Dann wähle ein Dictionary. +- Du brauchst nur eine geordnete Folge von Elementen? Dann wähle eine Liste. +- Du brauchst eine Sammlung von Elementen, auf die du später einzeln, gezielt und effizient mit Hilfe eines Namens (d.h. keys) zugreifen kannst? Dann wähle ein Dictionary. -Dictionaries sind, so wie auch Listen, *mutable*, d. h. nachträglich veränderbar. So kannst du bei Dictionaries später noch weitere key-value Paare hinzufügen: +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: + +{% filename %}command-line{% endfilename %} ```python >>> participant['favorite_language'] = 'Python' ``` -Wie bei Listen können wir auch bei Dictionaries die `len()`-Funktion verwenden, um die Zahl der enthaltenen Einträge (das sind die key-value Paare) zu ermitteln: Probier es gleich aus und tippe dieses Kommando ein: +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: + +{% filename %}command-line{% endfilename %} ```python >>> len(participant) 4 ``` -Wir hoffen, dass das Alles für dich bisher Sinn ergibt. :) Bist du bereit für mehr Spaß mit Dictionaries? Machen wir weiter. +I hope it makes sense up to now. :) Ready for some more fun with dictionaries? Read on for some amazing things. -Zum Löschen von Elementen kannst du den `del`-Befehl (oder im Englischen: statement) verwenden. Nehmen wir an, du möchtest den Eintrag mit dem key `'favorite_numbers'` entfernen: +You can use the `pop()` method to delete an item in the dictionary. Nehmen wir an, du möchtest den Eintrag mit dem key `'favorite_numbers'` entfernen: + +{% filename %}command-line{% endfilename %} ```python ->>> del participant['favorite_numbers'] +>>> participant.pop('favorite_numbers') +[7, 42, 92] >>> participant {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} ``` -Wie du an der Ausgabe erkennst, ist nun das key-value Paar von 'favorite_numbers' gelöscht. +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 this: -Ebenso kannst du auch den Wert eines bestehenden Eintrages ändern: +{% filename %}command-line{% endfilename %} ```python - >>> participant['country'] = 'Germany' - >>> participant - {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} ``` -Wie du siehst, hast du nun im key-value Paar mit dem key `'country'` den value von `'Poland'` nach `'Germany'` geändert. :) Hurra! Schon wieder was gelernt. +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. ### Zusammenfassung Großartig! Inzwischen hast du schon einiges über Programmierung gelernt und die folgenden Dinge sind dir vertraut: -* **Errors** - Du weißt wie sie zu lesen sind und dass Python sie dann ausgibt, wenn es eine Anweisung von dir nicht ausführen kann -* **Variable** - sind Namen für Objekte, die dir dabei helfen, deinen Code leichter zu schreiben und ihn dabei auch gut lesbar zu halten -* **Listen** - können Objekte in einer geordneten Reihenfolge speichern -* **Dictionaries** - speichern Objekte als key-value Paare +- **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 Schon gespannt auf den nächsten Teil? :) ## Vergleichen -Ein wichtiger Teil beim Programmieren besteht darin, Dinge zu vergleichen. Was lässt sich leicht vergleichen? Zahlen sicherlich. Schauen wir uns mal an, wie das funktioniert: +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% filename %}command-line{% endfilename %} ```python >>> 5 > 2 @@ -405,12 +491,14 @@ True True ``` -Hier haben wir Python einige Zahlen zum Vergleichen gegeben. Wie du siehst, kann Python nicht nur die Zahlen vergleichen, sondern auch die Ergebnisse von Berechnungen. Cool, nicht wahr? +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? -Womöglich wunderst du dich aber über die beiden `==` Gleichheitszeichen zum Vergleich, ob zwei Zahlen den selben Wert haben? Ein einfaches Gleichheitszeichen `=` verwenden wir bereits, um Werte Variablen zuzuweisen. Da beim Progammieren alle Anweisungen eindeutig sein müssen, benötigst du in Python daher **stets** zwei `==` Zeichen, um Dinge auf Gleichheit zu testen. Wir können auch festsetellen, ob Werte unterschiedlich sind. Dafür verwenden wir das Symbol `!=`, wie in obigen Beispiel. +Womöglich wunderst du dich aber über die beiden `==` Gleichheitszeichen zum Vergleich, ob zwei Zahlen den selben Wert haben? Ein einfaches Gleichheitszeichen `=` verwenden wir bereits, um Werte Variablen zuzuweisen. You always, **always** need to put two of them – `==` – if you want to check if things are equal to each other. Wir können auch festsetellen, ob Werte unterschiedlich sind. Dafür verwenden wir das Symbol `!=`, wie in obigen Beispiel. Nun noch zwei weitere Vergleiche: +{% filename %}command-line{% endfilename %} + ```python >>> 6 >= 12 / 2 True @@ -418,15 +506,17 @@ True False ``` -`>` und `<` sind klar, was aber sollen `>=` und `<=` bedeuten? Vergleiche liest du folgendermaßen: +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: -* x `>` y bedeutet: x ist größer als y -* x `<` y bedeutet: x ist kleiner als y -* x `<=` y bedeutet: x ist kleiner oder gleich y -* x `>=` y bedeutet: x ist größer oder gleich y +- x `>` y bedeutet: x ist größer als y +- x `<` y bedeutet: x ist kleiner als y +- x `<=` y bedeutet: x ist kleiner oder gleich y +- x `>=` y bedeutet: x ist größer oder gleich y Sensationell! Lust auf mehr? Dann probier das: +{% filename %}command-line{% endfilename %} + ```python >>> 6 > 2 and 2 < 3 True @@ -438,30 +528,37 @@ True Du kannst Python beliebig viele Vergleiche vornehmen lassen und wirst ein Ergebnis erhalten. Das ist wirklich cool, oder? -* **and** - wenn Du den `and`-Operator verwendest, müssen beide Vergleiche True (d.h. wahr) ergeben, damit das Gesamtergebnis auch True ist -* **or** - wenn Du den `or`-Operator verwendest, genügt es, wenn einer der beiden Vergleiche True ergibt, damit das Gesamtergebnis True ergibt +- **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 Die Redewendung "Äpfel mit Birnen zu vergleichen" hast du bestimmt schon einmal gehört. Machen wir dies doch einmal in Python: +{% filename %}command-line{% endfilename %} + ```python >>> 1 > 'django' Traceback (most recent call last): File "", line 1, in -TypeError: unorderable types: int() > str() +TypeError: '>' not supported between instances of 'int' and 'str' ``` Unterschiedliche Dinge, hier die Datentypen Zahlen (`int`) und Strings (`str`), lassen sich auch in Python nicht miteinander vergleichen. In solch einem Fall liefert uns Python einen **TypeError** und sagt uns, dass diese zwei Datentypen nicht miteinander verglichen werden können. ## Boolean -Zusammen mit den Vergleichen hast du auch einen weiteren Datentyp in Python kennengelernt. Ein **Boolean** -- dies ist ein Wahrheitswert (und wir bleiben auch hier bei der englischen Bezeichnung 'boolean') und es ist zudem auch der einfachste Datentyp überhaupt. +Incidentally, you just learned about a new type of object in Python. It's called **Boolean**. -Es gibt nur zwei boolsche Werte: - True - False (also wahr und falsch). +There are only two Boolean objects: -Damit Python diese beiden Werte versteht, musst du sie auch genau so schreiben (den ersten Buchstaben groß, alle weiteren klein). **true, TRUE, tRUE funktionieren nicht -- nur True ist korrekt.** (Dasselbe gilt natürlich auch für False.) +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well, of course.) Boolsche Werte können auch mit Variablen bezeichnet werden: +{% filename %}command-line{% endfilename %} + ```python >>> a = True >>> a @@ -470,6 +567,8 @@ True Auch Folgendes geht: +{% filename %}command-line{% endfilename %} + ```python >>> a = 2 > 5 >>> a @@ -478,73 +577,109 @@ False Übe ein wenig, indem du mit Booleans rumspielst, zum Beispiel mit diesen Anweisungen: -* `True and True` -* `False and True` -* `True or 1 == 1` -* `1 != 2` +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` Glückwunsch! Booleans sind echt eine der coolsten Features beim Programmieren und du hast gerade gelernt, damit umzugehen! # Sichern! +> 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. + Bisher haben wir den Python-Code nur im Interpreter eingegeben, wodurch wir immer nur eine Zeile Code auf einmal ausführen konnten. Richtige Programme dagegen werden in Dateien gespeichert und, je nach Programmiersprache, durch einen **Interpreter** ausgeführt oder durch einen **Compiler** übersetzt. Unseren bisherigen Code haben wir dagegen im Python-**Interpreter** Zeile für Zeile eingegeben und einzeln ausgeführt. Für die nächsten Beispiele brauchen wir mehr als eine Zeile, daher werden wir nun: -* Den Python-Interpreter beenden -* Einen Code-Editor unserer Wahl öffnen -* Code eingeben und diesen in einer Python-Datei sichern -* Und diesen dann laufen lassen! +- Den Python-Interpreter beenden +- Einen Code-Editor unserer Wahl öffnen +- Code eingeben und diesen in einer Python-Datei sichern +- Und diesen dann laufen lassen! + +To exit from the Python interpreter that we've been using, simply type the `exit()` function -Um den Python-Interpreter zu beenden, nutze einfach die ~~~ exit()~~~ Funktion: +{% filename %}command-line{% endfilename %} ```python >>> exit() -$ ``` Nun siehst du wieder den normalen Kommandozeilen-Prompt. Ein paar Kapitel zuvor hatten wir uns bereits einen [Code-Editor](../code_editor/README.md) ausgesucht. Diesen öffnest du nun und gibst Folgendes ein: +{% filename %}editor{% endfilename %} + ```python print('Hello, Django girls!') ``` -> **Hinweis:** Achte auf eines der tollsten Features von Code-Editoren: Farben! In der Python-Konsole hatte alles die gleiche Farbe. Der Code-Editor dagegen sollte dir nun die `print`-Funktion in einer anderen Farbe anzeigen als der von ihr auszugebende Text. Dies wird "Syntax Hervorhebung" ("syntax highlighting") genannt und ist ein wirklich sehr nützliches Werkzeug beim Coden. Die Farbe von Dingen gibt dir Hinweise auf z.B. nicht geschlossene Zeichenfolgen oder Tippfehler in einem Schlüsselwort (wie das `def` in einer Funktion, was wir weiter unten sehen werden). Dies ist einer der Gründe, warum wir Code-Editoren verwenden :) - Da du nun schon einige Python-Erfahrung hast, schreibe ein wenig Code mit dem, was du bislang gelernt hast. -Als nächstes wollen wir diesen Code in einer Datei mit einem aussagekräftigen Namen speichern. Lass uns die Datei **python_intro.py** nennen und auf dem Desktop speichern. Wir können der Datei jeden Namen geben, den wir wollen, aber es ist wichtig sicherzustellen, dass die Datei auf **.py** endet. Die **.py** Erweiterung gibt unserem Betriebssystem an, dass dies ein **python executable file** ist und Python diese ausführen kann. +Als nächstes wollen wir diesen Code in einer Datei mit einem aussagekräftigen Namen speichern. Lass uns die Datei **python_intro.py** nennen und auf dem Desktop speichern. Wir können der Datei jeden Namen geben, den wir wollen, aber es ist wichtig sicherzustellen, dass die Datei auf **.py** endet. The **.py** extension tells our operating system that this is a **Python executable file** and Python can run it. + +> **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. Dies wird "Syntax Hervorhebung" ("syntax highlighting") genannt und ist ein wirklich sehr nützliches Werkzeug beim Coden. 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). Dies ist einer der Gründe, warum wir Code-Editoren verwenden. :) Nun, da die Datei gesichert ist, wollen wir sie ausführen! Mit dem, was du bisher über die Kommandozeile (das mit dem Prompt) gelernt hast, öffnest du die Konsole und gehst in das Desktop-Verzeichnis. + + Auf einem Mac sieht das etwa so aus: -```bash -$ cd /Users//Desktop -``` +{% filename %}command-line{% endfilename %} -Unter Linux ist es ähnlich ("Desktop" könnte bei Dir allerdings "Schreibtisch" heißen): + $ cd ~/Desktop + -```bash -$ cd /home//Desktop -``` + -Nutzt Du dagegen Windows, schaut es wie folgt aus: + -```bash -> cd C:\Users\\Desktop -``` +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + Kommst du hier nicht weiter, frag jemanden um Hilfe. Benutze jetzt Python, um den Code in der Datei auszuführen: -```bash -$ python3 python_intro.py -Hello, Django girls! -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hello, Django girls! + -Hinweis: in Windows wird 'python3' nicht als Kommando erkannt. Nutze dafür einfach 'python' um die Datei auszuführen: +Note: on Windows 'python3' is not recognized as a command. Instead, use 'python' to execute the file: + +{% filename %}command-line{% endfilename %} ```python > python python_intro.py @@ -554,27 +689,32 @@ Prima! Du hast soeben dein erstes Python-Programm aus einer Datei heraus ausgef Nun wollen wir uns einem wichtigen Teil der Programmierung zuwenden: -## If...elif...else +## If … elif … else -Oft sollen manche Programmteile nur ausgeführt werden, wenn bestimmte Vorbedingungen erfüllt sind. Dafür gibt es in Python sogenannte **if Anweisungen**. +Lots of things in code should be executed only when given conditions are met. That's why Python has something called **if statements**. Nun ändere den Code in deiner **python_intro.py** Datei: +{% filename %}python_intro.py{% endfilename %} + ```python if 3 > 2: ``` -Wenn wir dieses nun sichern und anschließend ausführen, erhalten wir einen Fehler: +If we were to save and run this, we'd see an error like this: -```bash -$ 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 erwartet hier noch weiteren Programmcode, der ausgeführt werden soll, wenn die Bedingung `3 > 2` wahr ist (also `True` ergibt). Lassen wir Python “It works!” ausgeben. Dafür ändere erneut den Code in **python_intro.py**: +{% filename %}python_intro.py{% endfilename %} + ```python if 3 > 2: print('It works!') @@ -584,15 +724,21 @@ Du fragst dich nun, warum wir die angefügte Zeile mit 4 Leerzeichen eingerückt Nun sichere die Datei und führe sie noch einmal aus: +{% filename %}command-line{% endfilename %} + ```python -$ python3 python_intro.py +$ 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. + ### Was passiert, wenn eine Bedingung nicht True ist? In den vorigen Beispielen wurde Code ausgeführt, wenn eine vorhergehende Bedingung True ergab. Aber Python kennt auch `elif` und `else` Anweisungen: +{% filename %}python_intro.py{% endfilename %} + ```python if 5 > 2: print('5 is indeed greater than 2') @@ -602,12 +748,15 @@ else: Wenn dies ausgeführt wird, wird es anzeigen: -```bash -$ python3 python_intro.py -5 is indeed greater than 2 -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + 5 is indeed greater than 2 + -Wenn 2 größer als 5 wäre, würde die zweite Anweisung (die nach dem else) ausgeführt. Einfach, nicht wahr? Schauen wir uns nun an, wie `elif` funktioniert: +If 2 were a greater number than 5, then the second command would be executed. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} ```python name = 'Sonja' @@ -621,15 +770,18 @@ else: und ausgeführt erhalten wir: -```bash -$ python3 python_intro.py -Hey Sonja! -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hey Sonja! + Hast du bemerkt was passiert ist? `elif` lässt dich zusätzliche Bedingungen hinzufügen, die geprüft werden, falls die vorherige fehlschlägt. Du kannst so viele `elif` Bedingungen nach der anfänglichen `if` Anweisung hinzufügen, wie du magst. Zum Beispiel: +{% filename %}python_intro.py{% endfilename %} + ```python volume = 57 if volume < 20: @@ -648,27 +800,50 @@ else: Python läuft durch jeden Test der Reihe nach und gibt dann aus: -```bash -$ python3 python_intro.py -Perfect, I can hear all the details +{% 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. + ### Zusammenfassung -In den letzten drei Übungen hast du gelernt: +In the last few exercises you learned about: -* **Vergleiche vorzunehmen** - in Python kannst du Vergleiche mit den folgenden Operatoren `>`, `>=`, `==`, `<=`, `<` sowie `and` und `or` vornehmen -* **Boolsche Datentypen** zu verwenden - Dies sind Objekte, die nur zwei Werte annehmen können: `True` bzw. `False` -* **Dateien zu speichern** - also Programmcode in Dateien abzulegen, so dass du auch umfangreichere Programme schreiben kannst. -* **if...elif...else** - Anweisungen zu verwenden, so dass nur bestimmte Programmteile ausgeführt werden. +- **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 Und nun zum letzten Kapitel! ## Deine eigenen Funktionen! -Erinnerst du dich an Funktionen wie `len()`, die du in Python aufrufen kannst? Genau sowas kannst du auch selbst schreiben, und das schauen wir uns nun an! +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. -Eine Funktion ist eine Folge von Anweisungen, die Python ausführen soll. Jede Funktion beginnt mit dem Keyword (auf deutsch 'Schlüsselwort', aber diese Übersetzung ist nicht gebräuchlich) `def`, gefolgt von einem Funktionsnamen und Parametern. Aber nicht alle Funktionen brauchen Parameter. Beginnen wir mit einem einfachen Beispiel ohne Parameter. Ändere den Code in der Datei **python_intro.py** wie folgt: +Remember functions like `len()` that you can execute in Python? Well, good news – you will learn how to write your own functions now! + +Eine Funktion ist eine Folge von Anweisungen, die Python ausführen soll. Jede Funktion beginnt mit dem Keyword (auf deutsch 'Schlüsselwort', aber diese Übersetzung ist nicht gebräuchlich) `def`, gefolgt von einem Funktionsnamen und Parametern. Aber nicht alle Funktionen brauchen Parameter. Let's give it a go. Ändere den Code in der Datei **python_intro.py** wie folgt: + +{% filename %}python_intro.py{% endfilename %} ```python def hi(): @@ -684,13 +859,21 @@ Nun magst du dich fragen, warum wir am Ende der Datei den Namen der Funktion ein Schauen wir, was passiert, wenn wir die Datei ausführen: -```bash -$ python3 python_intro.py -Hi there! -How are you? -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: -Das war einfach! Als Nächstes bauen wir Funktionen mit sogenannten Parametern. Wir werden das gerade gebaute Beispiel benutzen - eine Funktion, die die ausführende Person begrüßt - aber diesmal mit Namen: +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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): @@ -698,6 +881,8 @@ def hi(name): Wie du siehst geben wir der Funktion jetzt einen Parameter, den wir `name` nennen: +{% filename %}python_intro.py{% endfilename %} + ```python def hi(name): if name == 'Ola': @@ -712,49 +897,59 @@ hi() Denk daran: Die `print` Funktion ist 4 Leerzeichen innerhalb der `if`-Anweisung eingerückt. Das ist sinnvoll, da die Funktion ausgeführt wird, wenn die Bedingung eintritt. Mal sehen, wie das jetzt funktioniert: -```bash -$ 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' + Hoppla, ein Fehler. Zum Glück gibt uns Python eine recht nützliche Fehlermeldung. Diese besagt, dass die Funktion `hi()` (welche wir definiert haben) ein erforderliches Argument hat (genannt `name`) und dass wir vergessen haben, dieses zu übermitteln, als wir die Funktion aufriefen. Lass uns das am unteren Ende der Datei schnell beheben: +{% filename %}python_intro.py{% endfilename %} + ```python hi("Ola") ``` Und wir führen sie erneut aus: -```bash -$ python3 python_intro.py -Hi Ola! -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Ola! + Und wenn wir den Namen ändern? +{% filename %}python_intro.py{% endfilename %} + ```python hi("Sonja") ``` Und ausgeführt: -```bash -$ python3 python_intro.py -Hi Sonja! -``` +{% filename %}command-line{% endfilename %} -Nun, was denkst du, wird passieren, wenn du einen anderen Namen dort hinein schreibst? (Nicht Ola oder Sonja!) Probier es aus und schau, ob du richtig liegst. Es sollte das Folgende herauskommen: + $ python3 python_intro.py + Hi Sonja! + -```bash -Hi anonymous! -``` +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: -Das ist genial, oder? Auf diese Weise musst du dich nicht jedesmal wiederholen, wenn du den Namen der Person änderst, die die Funktion grüßen soll. Und das ist genau der Grund, warum wir Funktionen brauchen - du willst auf keinem Fall deinen Code wiederholen! +{% filename %}command-line{% endfilename %} -Lass uns etwas Klügeres machen -- es gibt mehr Namen als nur zwei und für jeden eine Bedingung zu schreiben, wäre recht schwierig, richtig? + Hi anonymous! + + +Das ist genial, oder? Auf diese Weise musst du dich nicht jedesmal wiederholen, wenn du den Namen der Person änderst, die die Funktion grüßen soll. 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? + +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): @@ -765,35 +960,44 @@ hi("Rachel") Lass uns den Code aufrufen: -```bash -$ python3 python_intro.py -Hi Rachel! -``` +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + Herzlichen Glückwunsch! Du hast gerade gelernt, wie du Funktionen schreibst! :) ## Schleifen +> For readers at home: this part is covered in the [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) video. + Dies ist bereits der letzte Teil. Das ging doch schnell, oder? :) Programmierer wiederholen sich nicht gerne. Beim Programmieren geht es darum, Dinge zu automatisieren, so dass wir nicht jede Person mit ihrem Namen manuell grüßen müssen, richtig? Dies ist der Punkt an dem Schleifen nützlich werden. Erinnerst du dich noch an Listen? Lass uns eine Liste mit Mädchennamen erstellen: +{% filename %}python_intro.py{% endfilename %} + ```python girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] ``` Wir wollen alle mit ihrem Namen grüßen. Wir besitzen bereits die `hi`-Funktion, um dies zu tun, also lass sie uns in einer Schleife verwenden: +{% filename %}python_intro.py{% endfilename %} + ```python for name in girls: ``` -Die `for`-Anweisung verhält sich ähnlich der `if`-Anweisung; Code unter beiden muss 4 Leerzeichen eingerückt werden. +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. Hier ist der vollständige Code für die Datei: +{% filename %}python_intro.py{% endfilename %} + ```python def hi(name): print('Hi ' + name + '!') @@ -806,47 +1010,51 @@ for name in girls: Und wenn wir es ausführen: -```bash -$ 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 + Wie du sehen kannst, wird alles, was du innerhalb einer `for`-Anweisung eingerückt hast, für jedes Element der Liste `girls` wiederholt. Du kannst auch `for` auf Nummern beziehen, wenn du die `range`-Funktion benutzt: +{% filename %}python_intro.py{% endfilename %} + ```python for i in range(1, 6): - print(i) + print(i) ``` Das würde ausgeben: -``` -1 -2 -3 -4 -5 -``` +{% filename %}command-line{% endfilename %} + + 1 + 2 + 3 + 4 + 5 + `range` ist eine Funktion, die eine Liste von Nummern (eine nach der anderen) erschafft (die Nummern werden von dir als Parameter bereitgestellt). -Merk dir, dass die zweite dieser Nummern, die du als Parameter übergibst, nicht in der Liste enthalten ist, die von Python ausgegeben wird (das bedeutet, dass `range(1, 6)` von 1 bis 5 zählt, aber nicht die Nummer 6 enthält). Die liegt daran, weil "range" halb offen ist, was widerum bedeutet, dass es den ersten Wert enthält, aber nicht den letzten. +Merk dir, dass die zweite dieser Nummern, die du als Parameter übergibst, nicht in der Liste enthalten ist, die von Python ausgegeben wird (das bedeutet, dass `range(1, 6)` von 1 bis 5 zählt, aber nicht die Nummer 6 enthält). That is because "range" is half-open, and by that we mean it includes the first value, but not the last. ## Zusammenfassung Das ist alles. **You totally rock!** Das war ein heikles Kapitel, darum kannst du jetzt stolz auf dich sein. Wir sind definitiv stolz auf dich, dass du es so weit geschafft hast! -Du möchtest jetzt vielleicht kurz etwas anderes tun - stretchen, etwas herumlaufen, deine Augen ausruhen - bevor es weiter zum nächsten Kapitel geht. :) +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) +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/de/signup_pythonanywhere.md b/de/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/de/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/de/template_extending/README.md b/de/template_extending/README.md index bfb8e0668bb..3e500b6f209 100644 --- a/de/template_extending/README.md +++ b/de/template_extending/README.md @@ -2,109 +2,113 @@ Eine weitere praktische Sache von Django ist das **template extending**, Erweiterungen des Templates. Was bedeutet das? Damit kannst du Teile deiner HTML-Site für verschiedene Seiten deiner Website nutzen. -Dadurch musst du dich nicht in jeder Datei wiederholen, wenn du das gleiche Layout oder den gleichen Inhalt nutzen möchtest. Und wenn du etwas ändern willst, musst du das nicht in jedem Template machen, sondern nur einmal! +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! -## Base-Template erstellen +## Create a base template Ein Base-Template ist das grundlegende Template, welches dann auf jeder einzelnen Seite deiner Website erweitert wird. Wir erstellen jetzt eine `base.html`-Datei in `blog/templates/blog/`: -``` -blog -└───templates - └───blog - base.html - post_list.html -``` + blog + └───templates +     └───blog +             base.html +             post_list.html + Öffne sie, kopiere alles von `post_list.html` und füge es wie folgt in die `base.html`-Datei ein: +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html {% load staticfiles %} - - Django Girls blog - - - - - - - - -
-
-
- {% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
- {% endfor %} -
-
-
- +     +        Django Girls blog +         +         +         +         +     +     +         + +        
+            
+                
+                {% for post in posts %} +                    
+                        
+                            {{ post.published_date }} +                        
+                        

{{ post.title }}

+                        

{{ post.text|linebreaksbr }}

+                    
+                {% endfor %} +                
+            
+        
+     ``` Dann ersetze in `base.html` den gesamten `` (alles zwischen `` und ``) hiermit: +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html - -
-
-
- {% block content %} - {% endblock %} -
-
-
+     +    
+        
+            
+            {% block content %} +            {% endblock %} +            
+        
+    
``` -Wir haben nun also alles zwischen `{% for post in posts %}{% endfor %}` ersetzt mit: +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% block content %} {% endblock %} ``` -Was bedeutet das jetzt? Du hast gerade einen `block` erstellt. Dies ist ein Template Tag, mithilfe dessen du HTML innerhalb dieses Blocks in anderen Templates einsetzen kannst, die sich auf `base.html` beziehen. Wir zeigen dir gleich, wie das geht. +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). Wir zeigen dir gleich, wie das geht. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} -Speichere nun und öffne wieder `blog/templates/blog/post_list.html`. Lösche hier alles, was nicht im Body steht und lösche auch ``, die Datei sollte dann so aussehen: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
+    
+        
+            {{ post.published_date }} +        
+        

{{ post.title }}

+        

{{ post.text|linebreaksbr }}

+    
{% endfor %} ``` -Schreibe nun diese Zeile an den Anfang: +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 %}`. So hier: -Das heißt, dass das `post_list.html`-Template nun das `base.html`-Template erweitert ("extend"). Als Letztes müssen wir noch Folgendes machen: Verschiebe alles (außer der Zeile, die wir gerade hinzugefügt haben) zwischen `{% block content %}` und `{% endblock content %}`. So hier: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html -{% extends 'blog/base.html' %} - {% block content %} {% for post in posts %}
@@ -118,6 +122,26 @@ Das heißt, dass das `post_list.html`-Template nun das `base.html`-Template erwe {% endblock %} ``` -Das war's! Probier aus, ob deine Website noch richtig funktioniert :) +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' %} + +{% block content %} +    {% for post in posts %} +        
+            
+                {{ post.published_date }} +            
+            

{{ post.title }}

+            

{{ post.text|linebreaksbr }}

+        
+    {% endfor %} +{% endblock %} +``` + +Das war's! Probier aus, ob deine Website noch richtig funktioniert. :) -> Wenn du einen Fehler `TemplateDoesNotExists` bekommst, mit dem Hinweis, dass es keine `blog/base.html`-Datei gibt und der Server in der Konsole noch läuft: Stoppe ihn mit Ctrl+C (Control und C zusammen drücken) und starte ihn nochmal neu mit dem Befehl `python manage.py runserver`. +> 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. \ No newline at end of file diff --git a/de/whats_next/README.md b/de/whats_next/README.md index df46f6dd36c..694921834cd 100644 --- a/de/whats_next/README.md +++ b/de/whats_next/README.md @@ -6,21 +6,20 @@ Herzlichen Glückwunsch! **Du bist der Hammer!** Wir sind echt stolz! <3 Mach eine Pause und entspanne. Du hast gerade etwas wirklich Großes geleistet. -Danach: - -* Folge den Django Girls auf [Facebook](http://facebook.com/djangogirls) oder [Twitter](http://twitter.com/djangogirls), um auf dem Laufenden zu bleiben. +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. ### Gibt es Empfehlungen für weiteren Quellen? -Ja! Auf dieser Seite gibt es noch empfehlenswerte Erweiterungen [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org). Schau mal rein.. +Yes! First, go ahead and try our other book, called [Django Girls Tutorial: Extensions](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). -Später kannst du die unten aufgeführten Ressourcen versuchen. Alles sehr empfehlenswert! +Later on, you can try the resources listed below. They're all very recommended! -- [Django's official tutorial](https://docs.djangoproject.com/en/1.8/intro/tutorial01/) +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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 1.8 book](http://twoscoopspress.com/products/two-scoops-of-django-1-8) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/dv-MV/GLOSSARY.md b/dv-MV/GLOSSARY.md new file mode 100644 index 00000000000..ee563bd7588 --- /dev/null +++ b/dv-MV/GLOSSARY.md @@ -0,0 +1,3 @@ +# ކޯޑު އެޑިޓަރ + +ކޯޑު އެޑިޓަރ އަކީ ފަހުން ބޭނުންކުރެވޭ ގޮތަށް ކޯޑު ލިޔެ ރައްކާ ކުރެވޭ އެޕްލިކޭޝަންއެއް. ކޯޑު އެޑިޓަރ އެއް ހޯދުމަށް[Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/dv-MV/README.md b/dv-MV/README.md new file mode 100644 index 00000000000..121da8f55bf --- /dev/null +++ b/dv-MV/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Introduction + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/dv-MV/SUMMARY.md b/dv-MV/SUMMARY.md new file mode 100644 index 00000000000..2b9bb97a2a0 --- /dev/null +++ b/dv-MV/SUMMARY.md @@ -0,0 +1,35 @@ +# ޚުލާސާ + +* [ތައާރަފު](README.md) +* [އިންސްޓޮލޭޝަން](installation/README.md) + * [Command Line](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Code Editor](installation/README.md#code-editor) + * [Virtual Environment](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [ކްރޯމްބުކް އިންސްޓޮލޭޝަން](chromebook_setup/README.md) +* [އިންޓަރނެޓް މަސައްކަތް ކުރާގޮތް](how_the_internet_works/README.md) +* [ކޮމާންޑްލައިންގެ ތައާރަފު](intro_to_command_line/README.md) +* [ޕައިތަން އިންސްޓޮލޭޝަން](python_installation/README.md) +* [ކޯޑު އެޑިޓަރ](code_editor/README.md) +* [ޕައިތަންގެ ތައާރަފު](python_introduction/README.md) +* [ޖޭންގޯ އަކީ ކޯއްޗެއް?](django/README.md) +* [ޖޭންގޯ އިންސްޓޮލޭޝަން](django_installation/README.md) +* [މަގޭ ފުރަތަމަ ޖޭންގޯ ޕްރޮޖެކްޓް!](django_start_project/README.md) +* [ޖޭންގޯ މޮޑެލްސް](django_models/README.md) +* [ޖޭންގޯ އެޑްމިން](django_admin/README.md) +* [ޑިޕްލޯއި!](deploy/README.md) +* [Django URLs](django_urls/README.md) +* [ޖޭންގޯ ވިއުސް!](django_views/README.md) +* [އެޗްޓީއެމްއެލްގެ ތައާރަފް](html/README.md) +* [ޖޭންގޯ އޯއާރުއެމް ( ކުއެރީ ސެޓްސް)](django_orm/README.md) +* [ޓެމްޕްލޭޓްސް ގައިވާ ބަދަލުވާ ޑޭޓާ](dynamic_data_in_templates/README.md) +* [ޖޭންގޯ ޓެމްޕްލޭޓްސް](django_templates/README.md) +* [ސީއެސްއެސް - ރީތިކުރުމަށް](css/README.md) +* [ޓެމްޕްލޭޓް އެކްސްޓެންޑިންގް](template_extending/README.md) +* [އެޕްލިކޭޝަން އެކްސްޓެންޑު ކުރުމަށް](extend_your_application/README.md) +* [ޖޭންގޯ ފޯރމުތައް](django_forms/README.md) +* [ދެން އޮތީ ކޯއްޗެއް?](whats_next/README.md) \ No newline at end of file diff --git a/dv-MV/chromebook_setup/README.md b/dv-MV/chromebook_setup/README.md new file mode 100644 index 00000000000..1dbeb4dd38d --- /dev/null +++ b/dv-MV/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# ކްރޯމްބުކް ސެޓަޕްކުރުން + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/dv-MV/chromebook_setup/instructions.md b/dv-MV/chromebook_setup/instructions.md new file mode 100644 index 00000000000..70540afe0b5 --- /dev/null +++ b/dv-MV/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +ކްރޯމްބުކް ބޭނުންނުކުރާނަމަ[މިސެކްޝަން ](http://tutorial.djangogirls.org/en/installation/#install-python)ދޫކޮށްލާ. ބޭނުންކުރާނަމަ، އިންސްޓޮލޭޝަންގެ ތަޖުރިބާ ތަންކޮޅެއް ތަފާތުވާނެ. ދެންބާކީހުރި އިންސްޓޮލޭޝަން އިރުޝާދުތައް ދޫކޮށްލެވިދާނެ. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +ކްލައުޑް އައިޑީއީ ނުވަތަ ކްލައުޑުގައި ސޮްފްޓްވެއަރ ތައްޔާރުކުރުމަށް ބޭނުންކުރާ އެޕްލިކޭޝަން އަކީ ކޯޑު ލިޔެ އަދި އިންޓަރނެޓުގައިވާ ކޮމްޕިއުޓަރކަށް ވަދެ ، ސޮފްޓްވެއަރ އިންސްޓޯލްކޮށް، ލިޔެ އަދި ސޮފްޓްވެއަރ ރަން ކުރެވޭނެ ގޮތް ހަދާއެއްޗެއް. މިޓިއުޓޯރިއަލް ހަދާއިރު،*local machine* އަކީ ކްލައުޑް އައިޑީއީ. ކްލާހުގައިތިބި OS X, Ubuntu, or Windows ބޭނުންކުރާ އެހެންބައިވެރިންނެކޭ އެއްގޮތަށް ތިބާވެސް ކޮމާންޑުތައް ޖައްސާނީ ޓަރމިނަލް އިންޓަރފޭސްގައި. އެކަމަކު މިޓަރމިނަލް ގުޅިފައި އިންނާނީ ކްލައުޑް އަޑީއީއިން ހަމަޖައްސައިދޭ އެހެންތަނެއްގައި އިން ކޮމްޕިއުޓަރަކާއެވެ. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). ކޮންމެވެސް 1 ކްލައުޑު އައިޑީއީެއް ނަގާ، އަދި ނެގި ކްލައުޑު އައިޑީއީގެ އިރުޝާދުތައް ބަަލަމުންދޭ. + +#### PaizaCloud Cloud IDE + +1. 1. paizaCloud Cloud IDE [](https://paiza.cloud/)ނަގާ +2. އެކައުންޓެއްހަދާ +3. Click *New Server* and choose the Django app +4. ޓާރމިނަލް ބަޓަން( ވިންޑޯގެ ވާތްފަރާތުގައި) އަށް ފިތާލާ + +މީހާރު ސައިޑްބާރ އާއެކު އިންޓަރފޭސްއެއް ފެންނާނެ، ބަޓަންތައް ވާތްފަރާތުގައި. މި މެސެޖް ފެންނަ ޓަރމިނަލް ހުޅުވުމަށް "Terminal" ބަޓަން އަށް ފިތާލާ: + +{% filename %} ޓަރމިނަލް{% endfilename %} + + $ + + +PaizaCloud Cloud IDE ގައިވާ ޓާރމިނަލްވަނީ ތިޔަފަރާތުގެ އިރުޝާދުތަކަށް ތައްޔާރުވެފައި. ވިންޑޯގެ ސައިޒުބޮޑުކޮށް ނުވަތަ ބަދަލުކުރެވޭނެ. + +#### އެމޭޒަން ވެބްސަރަވިސް ކްލައުޑު 9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + $ yourusername:~/workspace + + +This bottom area is your terminal. You can use the terminal to send instructions to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### ވާރޗުއަލް އެންވަރމަންޓް + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(note that on the last line we use a tilde followed by an equal sign: `~=`). + +### ގިޓްހަބް + +Make a [GitHub](https://github.com) account. + +### ޕައިތަންއެނީވެއަރ + +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 for 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). \ No newline at end of file diff --git a/dv-MV/code_editor/README.md b/dv-MV/code_editor/README.md new file mode 100644 index 00000000000..7ab3cc714f6 --- /dev/null +++ b/dv-MV/code_editor/README.md @@ -0,0 +1,11 @@ +# ކޯޑު އެޑިޓަރ + +> ކިޔުންތެރިންނަށް: [އިންސްޓޯލިން ޕައިތަން & ކޯޑު އެޑިޓަރ ](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) ވީޑިއޯގައި މިޗެޕްޓަރ ހިމެނިފައިވާނެއެވެ. + +މިހާރު ތިއުޅެނީ އެންމެ ފުރަމަ ކޯޑުގެ ލައިން ލިޔާށެވެ. ކޯޑު އެޑިޓަރ އެއް ޑައުންލޯޑު ކުރާ ވަގުތު ޖެހުނީއެވެ! + +> **ނޯޓު** ކްރޯމްބުކް ބޭނުންކުރާނަމަ، މިޗެޕްޓަރ ދޫކޮށްލާށެވެ. އަދި [ކްރޯމްބުކް ސެޓަޕް](../chromebook_setup/README.md) ގެ އިރުޝާދުތައް ބަލާށެވެ. ކުރިން ނަގާފައިވާ ކްލައުޑު އައިޑީއީ ( ޕައިޒާ ކްލައުޑު އައިޑީއީ އަދި އޭޑަބްލިއުއެސް ކްލައުޑު 9) ގައި ކޯޑު އެޑިޓަރއެއް ހިމެނޭއެވެ، އައިޑީއީގެ ފައިލް މެނޫއިން ފައިލްއެއް ހުޅުވީމާ އެޑިޓަރ އޮޓޯއިން ބޭނުންކުރެވުނީއެވެ. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/dv-MV/code_editor/instructions.md b/dv-MV/code_editor/instructions.md new file mode 100644 index 00000000000..00e7ebb9ccc --- /dev/null +++ b/dv-MV/code_editor/instructions.md @@ -0,0 +1,37 @@ +ވަރަށް ގިނަ އެޑިޓަރތައް ހުންނައިރު ބޭނުންކުރާނެ އެޑިޓަރ އެއްއޮންނަނީ އަމިއްލަ އިޚްތިޔާރުގައެވެ. ގިނަ ޕައިތަން ޕްރޮގްރާމް ހަދާ މީހުން ބޭނުންކުރަނީ PyCharm ފަދަ އުނދަގޫ އެކަމަކު ވަރަށް ބާރުގަދަ އައިޑީއީ ތަކެއް( Integrated Development Environments). ފަށައިގަންނަ މީހަކަށް އެފަދަ އައިޑީއެއް ބޭނުން ނުވާނެ: އަހަރެމެން ކިޔައިދޭނީ ހަމަ އެފަދަ ބާރުގަދަ އެކަމަކު އާދައިގެ އައީޑީތަކެކެވެ. + +ތިރީގައި އެވަނީ އަހަރެމެންނަށް ފެންނަ އެޑިތަރުތަކެވެ. ކޯޗު ބޭނުން ވަކި އެޑިޓަރ އެއް އިންތޯ އަހާށެވެ. އެއީ ކޯޗުގެ އެހީ ހޯދަން ފަސޭހަވާނެތީވެ. + +## Visual Studio Code + +Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + +[މިތަނުން ޑައުންލޯޑު ކުރޭ](https://code.visualstudio.com/) + +## Gedit + +Gedit is an open-source, free editor, available for all operating systems. + +[މިތަނުން ޑައުންލޯޑު ކުރޭ](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[މިތަނުން ޑައުންލޯޑު ކުރޭ](https://www.sublimetext.com/3) + +## Atom + +Atom is another popular editor. It's free, open-source and available for Windows, OS X and Linux. Atom is developed by [GitHub](https://github.com/). + +[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. :) \ No newline at end of file diff --git a/dv-MV/css/README.md b/dv-MV/css/README.md new file mode 100644 index 00000000000..11b2b7aa7f8 --- /dev/null +++ b/dv-MV/css/README.md @@ -0,0 +1,330 @@ +# ސީއެސް އެސް - ރީތިކުރުމަށް! + +އަހަރެމެންގެ ބްލޮގް ހަޑިދޯ؟ މިއީ ބްލޮގް ރީތި ކޮށްލާ ވަގުތު! މިކަމަށް ބޭނުން ކުރާނީ ސީއެސްއެސް. + +## ސީ އެސް އެސް އަކީ ކޯއްޗެއް؟ + +ކެސްކޭޑިން ސްޓައިލްޝީޓްސް ( ސީއެސް އެސް) އަކީ މާރކްއަޕް ލެންގުއޭޖުން ( އެޗްޓީއެމްއެލް ފަދަ) ލިޔަފައި ހުންނަ ވެބްސައިޓް ފެންނަގޮތް އަދި ފޯރމެޓިން އިންނަންވާގޮތް ކިޔައިދޭ ލެންގުއޭޖެކެވެ. ވެބްޕޭޖްގެ މޭކަޕް ގެ ގޮތަށް ގެންގުޅުން ރަނގަޅުވާނެ :) + +އެކަމަކު އަލުން ފަށާކަށް ބޭނުމެއް ނޫންދޯ؟ އަދި އެއްފަހަރު، އެކި ޕްރޮގްރާމަރުން އިންޓަރނެޓްއަށް ދޫކޮށްފައިހުރި ހިލޭ ބޭނުންކުރެވޭ ތަކެތި ބޭނުންކޮށްލާނަމެވެ. އަލުން ހުރިހާ އެއްޗެއް ހެދުމަކީ މަޖާކަމެއް ނޫން. + +## ބޫްޓް ސްޓްރެޕް ބޭނުންކުރަން ހިނގާ! + +ބޫޓްސްޓްރެޕްއަކީ ރީތި ވެބްސައިޓް ހެދުމަށްޓަކައި ބޭނުންކުރާ އެޗްޓީއެމްއެލް އަދި ސީއެސްއެސް ފްރޭމްވޯރކްއެވެ.: /https://getbootstrap.com + +މީތި ލިޔެފައިވަނީ ޓުވިޓާއަށް ކުރިން މަސައްކަތްކުރި ޕްރޮގްރާމަރުން ތަކެކެވެ. މިހާރު މީތި ތައްޔާރުކުރަނީ ދުނިޔޭގެ އެކިތަންތަނުގައި ތިބި ހިލޭ ސާބަހަށް މަސައްކަތްކުރާ މީހުންނެވެ! + +## ބޫޓްސްޓްރެޕް އިންސްޓޯލް ކުރޭ + +ބޫޓްސްޓްރެޕް އިންސްޓޯލްކުރުމަށް، `.html` ފައިލް ކޯޑު އެޑިޓަރގައި ހުޅުވާ އަދި `` މީތި ސެކްޝަން އަށް ލާށެވެ: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +މީގެއިން ޕްރޮޖެކްޓްއަށް އެއްވެސް ފައިލްއެއް ނޭޅޭނެއެވެ. މީގެއިން އިންޓަރނެޓްގައި ވާ ފައިލްތަކަށް ޕޮއިންޓްކުރާނެއެވެ. އެހެންވީމާ، ވެބްސައިޓް ހުޅުވާފައި ޕޭޖް ރީފްރެޝް ކޮށްލާށެވެ. މިއޮތީ! + +![Figure 14.1](images/bootstrap1.png) + +މިހާރުވެސް ރީތިވެއްޖެ! + +## ޖެންގޯގައިވާ ސްޓެޓިކް ( ބަދަލުނުވާ) ފައިލްތައް + +**ސްޓެޓިިިކް ފައިލްސް** އޭ މިކިޔާ އެއްޗަށް ތަންކޮޅެއް ކައިރިން ބަލާލާނަމެވެ. ސްޓެޓިކް ފައިލްސް އަކީ ސީއެސް އެސް އަދި އިމޭޖް ތައް. މީގެ ކޮންޓެންޓުތައް ކޮންމެ ރިކުއެސްޓަކަށް (ސަރވާއަށް ފޮނުވާ ރިކުއެސްޓް) ނުބަލާނެ އަދި ބޭނުންކުރާމީހަކަށްވެސް ތަފާތެއް ނުވާނެއެވެ. + +### ޖެންގޯގައި ސްޓެޓިކް ފައިލްތައް ލާނީ ކޮންތަނަކަށް + +"އެޑްމިން" އެޕްގެ ސްޓެޓިކް ފައިލްތައް ލާން ޖެހޭތަން ޖެންގޯއަށް އިނގޭނެއެވެ. އަހަރެމެންގެ އަމިއްލަ `blog` އެޕްއަށް ސްޓެޓިކް ފައިލްތައް ލާންވީ. + +ފައިލްތައް ލާނީ ބްލޮގް އެޕްގައި `static`ނަމުގައި ފޯލްޑަރ އެއް ހަދައިގެން: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │ └── templates + └── mysite + + +އެއްވެސް އެޕް ފޯލްޑަރ އެއްގައި "static" ފޯލްޑަރ އެއް އިންތޯ ޖެންގޯއިން ހޯދާނެ. ސްޓެޓިކް ފައިލްގައި ހުރި އެއްޗެއް ބޭނުންކުރެވޭނެ. + +## އެންމެ ފުރަތަމަ ސީއެސްއެސް ފައިލް! + +އެންމެ ފުރަތަމަ ހިނގާ ސީއެސްއެސް ފައިލް އެއް ހަދަން، ވެބް ޕޭޖަށް އަމިއްލަ ސްޓައިލް އެއް ލާން. `static` ޑިރެކްޓްރީ ތެރޭގައި `css` ޖަހާފައި އާ ޑިރެކްޓްރީ އެއް ހަދާ. ދެން `css` ޑިރެކްޓްރީ ތެރޭގައި `blog.css` ނަމުގައި އާ ފައިލް އެއް ހަދާ. ތައްޔާރުތަ? + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +މިއީ ސީއެސް އެސް ތަކެއް ލިޔަންވީ ވަގުތު! ކޯޑު އެޑިޓަރުގައި `blog/static/css/blog.css` ފައިލް ހުޅުވާ. + +މިތަނުގައި ސީއެސްއެސް ތަފްސީލުކޮށް ކަސްޓަމައިޒްކޮށް ދަސްކުރަން ކިޔައެއް ނުދޭނެ. އިތުރަށް ދަސްކުރަން ބޭނުންނަމަ މި ޕޭޖްގެ ތިރީގައި ހިލޭ ކިޔެވޭ ސީއެސްއެސް ކޯސްތައް ކިޔައިދީފައި ހުންނާނެ. + +އެކަމަކު ކުޑަކޮށް ކަސްޓަމައިޒް ކުރެވިދާނެ. ހެޑަރސްގެ ކުލަ ބަދަލުކޮށްލެވިދާނެ ދޯ? ކުލަ ދަސްކުރުމަށް، ޚާއްސަ ކޯޑުތަކެއް ކޮމްޕިއުޓަރ ގެންގުޅޭ. މިކޯޑުތައް ފެށޭނީ `#` އިން ދެން ފަހަތަށް 6 އަކުރު (A–F) އަދި ނަމްބަރު(0–9). މިސާލަކަށް، ނޫކުލައިގެ ކޯޑަކީ0000FF `#` ގިނަ ކުލަތަކުގެ ކޯޑު ލިބޭނީ http://www.colorpicker.com. `green ` އަދި `red` ފަދަ [ޕްރީޑިފައިންޑް ކުލަތައް](http://www.w3schools.com/colors/colors_names.asp) ބޭނުންކުރެވޭނެ. + +`blog/static/css/blog.css` ފައިލް އަށް ތިރީގައިވާ ކޯޑު އިތުރުކުރޭ: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1 a` އަކީ ސީއެސްއެސް ސިލެކްޓަރ އެއް. މީގެ މާނައަކީ އަހަރެމެންގެ ސްޓައިލްތައް `h1` ތެރޭގައި ހިމެނޭ `a` ބަޔަކަށް ލަނީއޭ: `h2 a` ސިލެކްޓަރ ވެސް `h2` ގެ ބައިތަކަށް ހަމަ މިގޮތަށް ހަަދަނީ. އެހެންވީމާ `

link

` ގޮތަށް ހުންނަ ތަންތަނަށް`h1 a` ސްޓައިލް އެޕްލައިވާނެ. މިހާރު، މިބުނަނީ ކުލަ `C25100 ކަޅު އޮރެންޖް ކުަލައަށް ބަދަލުކުރުމަށް. ނޫނީ އަމިއްލަޔަށް ބޭނުންވާ ކުަލައެއްވެސް ލިޔެވިދާނެ، އެކަމަކު ހުދު ބެކްގްރައުންޑެއްގައި ބޭނުންކުރީމައި ރަނގަޅަށް ފެންނަ ކުލައެއްތޯ ބަލާތި!

+ +

އެޗްޓީއެމްއެލްގައިވާ ބައިތަކަށް ބޭނުންވާ ސްޓްއިލްތައް ސީއެސްއެސް ފައިލް އިން ކިޔައިދޭ. ކޮންމެ އެލިމެންޓް ( ބައެއް) ވެސް ވަކިކުރަނީ އެބަޔަކަށް ކިޔާނަމުން. އެޗްޓީއެމްއެލް ސެކްޝަންއިން ޓެގްސްގެ ގޮތުގައި ހަނދާން ވެދާނެ. މިގޮތުން a`، `h1` އަދި `body` އަކީ މިފަދަ ބައިތަކުގެ ނަންތައް. އެޓްރިބިއުޓު `class` ނުވަތަ އެޓްރިބިއުޓު `id<0>އިންވެސް އެލިމެންޓްއެއް ވަކިކުރެވިދާނެ. އެލިމެންޓެއްގެ ކްލާސް އަދި އައިޑީ ނަމަކީ އެމީހަކު އަމިއްލަޔަށް ދޭ ނަމެއް. ކްލާހެއްގައި ހިމެނެނީ ގުރޫޕްކުރެވިފައިވާ އެލިމެންޓްތަކެއް، އަދި އައިޑީއިން ޕޮއިންޓުކުރަނީ ވަކި ވަކި އެލިމެންޓުތަކަށް. For example, you could identify the following element by using the element name a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +އިތުރަށް ކިޔާލަން [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +ސީއެސް އެސް އިތިރުކުރި އެޗްޓީއެމްއެލް ޓެމްޕްލޭޓް އާއި ގުޅޭގޮތުން ކިޔައިދޭން އެބަޖެހޭ. `blog/templates/blog/post_list.html` ފައިލް ކޯޑު އެޑިޓަރގައި ހުޅުވާ އަދި ފަށާބަޔަށް މިލައިން އިތުރުކުރޭ: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +މިތަނުން ލޯޑު މިކުރަނީ ހަމައެކަނި ސްޓެޓިކް ފައިލްސް :) ``and`` ޓެގުތަކުގެ ދޭތެރޭ އަދި ބޫޓުސްޓްރެޕް ސީއެސް އެސް ފައިލްސްގެ ލިންކު ފަހަތަށް މިލައިން އިތުރުކުރޭ: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +ބްރައުޒާއިން ނަގާނީ ފައިލްތައް ދޭ ތަރުތީބުން، އެހެންވީމާ ރަނގަޅަށް ދޭން ޔަގީންކުރަންޖެހޭ. ނޫނީ އަހަރެމެންގެ ފައިލްގެ މައްޗަށް ބޫޓްސްޓްރެޕް ފައިލް ލެވިދާނެ. އަހަރެމެންގެ ޓެމްޕްލޭޓަށް މިކިޔައިދިނީ ސީއެސްއެސް ފައިލް އިންތަން. + +މިހާރު ފައިލް އިންނަންވާނީ މިހެން: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +

+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +އޯކޭ، ފައިލް ސޭވްކޮށްފައި ސައިޓް ރީފްރެށްކޮށްލާ! + +![Figure 14.2](images/color2.png) + +ސަޅި: މިހާރު ކުޑަކޮށް ވެބްސައިޓް ބޮޑުކޮށްލާ އަދި ކަނާތްފަރާތުގެ މާރޖިން ބޮޑުކޮށްލަން މަސައްކަތްކޮށްލަންވީ. މިހެން ހަދަން ހިނގާ! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +ސީއެސްއެސް ފައިލް އަށް ކޯޑުކޮޅު އިތުރުކޮށްފައި ސޭވްކޮށްލީމާ މަސައްކަތްކުރޭތޯ ބަލަންވީއެންނު! + +![Figure 14.3](images/margin2.png) + +ހެޑަރގައި އިން ފޮންޓު ކަސްޓަމައިޒްކޮށްލަން ވީއެންނު؟ މިލައިން ޕޭޖުގެ `` in `blog/templates/blog/post_list.html` file ހިމަނާލަންވީނު: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +ކުރިންވެސް ހެދި ގޮތށް، އޯރޑަރޗެކްކޮށްފައި މިލިންކު `blog/static/css/blog.css` ގެ ކުރިޔަށް އިތުރުކުރޭ. މިލައިންއިން *Lobster* ނަމުގައި އިން ފޮންޓެއް ގޫގުލް ފޮންޓް އިން އިމްޕޯރޓް ކުރާނެ. (https://www.google.com/fonts). + +`blog/static/css/blog.css` ސީއެސް އެސްފައިލްގެ ޑިކްލެރޭޝަން ބްލޮކް ( ބްރެކެޓް ދޭތެރޭގައިވާ ކޯޑުތައް `{` and `}`) އިން `h1 a` ހޯދާ. ދެން `font-family: 'Lobster';` މިލައިން ބްރެކެޓްތަކުގެ ދޭތެރެއަށް އިތުރުކޮށްފައި ޕޭޖު ރިފްރެޝްކޮށްލާ: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +ގަދަ! + +މަތީގައިވެސް ބުނިގޮތަށް، ސީއެސްއެސްގައި އިންނަނީ ކްލާސްތަކުގެ ކޮންސެޕްޓް. އެޗްޓީއެމްއެލްގެ ކޯޑުގެ ވަކިބަޔަކަށް ސްޓައިލް އެޕްލައިކުރާއިރު އަނެއް ބަޔަށް އަސަރު ނުކުރާ ގޮތަށް އެޕްލައިކުރެވޭނެ. މިއީ ވަރަށް ބޮޑު އެހީއެއް! ފަހަރެއްގައި ދެ ޑިވް އެއް އިނދެފާނެ ތަފާތު ދެކަމެއް ކުރާ ( ހެޑަރ އަދި ޕޯސްޓް ގޮތައް). ކިލާހަކުން މިދޭތި ފެންނަގޮތް ތަފާތުކުރަން އެހީތެރިވޭ. + +Go ahead and name some parts of the HTML code. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +ދެން އެކި ސެލެކްޓަރސް އަށް ވަކިވަކި ޑެކްލެރޭޝަން ބްލޮކް ލާނީ. ފުރަތަމަ `.` އާއި ގުުޅުންހުރި ސެލެކްޓަރސް އިން ފަށާނީ. މިކޯޑުތައް ދަސްކުރުމަށް އިންޓަރނެޓުގައި ސީއެސްއެސްއާއި ގުޅުންހުރި ވަރަށްގިނަ ޓިއުޓޯރިއަލްއާއި ތަފްސީލުތައް އެބަހުރި. މިހާރަށް، `blog/static/css/blog.css` file: ކޮޕީކޮށްފައި ޕޭސްޓުކޮށްލާ: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +ނަ ކްލާސް ޑިކްލެރޭޝަންތައް ހިމެނޭ އެޗްޓީއެމްއެލް ކޯޑުތައް ނަގާފައި، މިގޮތަށް ބަދަލުކޮށްލާ: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +`blog/templates/blog/post_list.html` މިގޮތަށް: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +ފައިލް ސޭވްކޮށްފައ ވެބްސައިޓް ރީފްރެޝްކޮށްލާ. + +![Figure 14.4](images/final.png) + +ސާބަހޭ! ރީތިދޯ? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/dv-MV/deploy/README.md b/dv-MV/deploy/README.md new file mode 100644 index 00000000000..cc2d165200c --- /dev/null +++ b/dv-MV/deploy/README.md @@ -0,0 +1,246 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/dv-MV/deploy/install_git.md b/dv-MV/deploy/install_git.md new file mode 100644 index 00000000000..9641950fdc8 --- /dev/null +++ b/dv-MV/deploy/install_git.md @@ -0,0 +1,52 @@ +ގިޓް އަކީ ގިނަ ޕްރޮގްރާމަރުން ބޭނުންކުރާ " ވާރޝަން ކޮންޓްރޯލް ސިސްޓަމް". މި ސޮފްޓްވެއަރ އިން ފައިލަކަށް ގެންނަ ބަދަލު ބަލަމުންގެންދާނެ އަދި ބޭނުންވާ ވާރޝަންއެއް ހޯދައިދޭނެ. ވޯރޑު ޕްރޮސެސަރ ( މައިކްރޮސޮފްޓް ވޯޑު ނުވަތަ ލިބްރޭ އޮފީސް ރައިޓަރ ފަދަ) ގައި އިންނަ " ޓްރެކް ޗޭންޖެސް" ފީޗަރ ގޮތައް އެކަމަކު އެއަށްވުރެ ބާރުގަދަ އެއްޗެއް. + +## ގިޓު އިންސްޓޯލްކުރުން + + + +git-scm.com އިން ގިޓު ޑައުންލޯޑު ކުރެވޭނެ. ދެ ސްޓެޕް ފިޔަވައި ދެން ހުރި ހުރިހާ ބަޔަކަށް"ނެކްސްޓް" ނެގޭނެ: އެޑިޓަރ އެއް ނަގަން ބުނާ ސްޓެޕްގައި ، ނެނޯ ނަގާފައި އަދި " އެޖަސްޓިން ޔުައަރ ޕާތް އެންވަޔަރމަންޓް" ގައި " ޔޫޒް ގިޓް އެންޑް އޮޕްޝަނަލް ޔުނިކްސް ޓޫލްސް ފްރޮމް ވިންޑޯސް ކޮމާންޑް ޕްރޮމްޕުޓް" ( ތިރީގައިވާ އޮޕްޝަން) ނަގާ. އެބައިތައް ނުލާ، އެހެން ހުރިހާތަނަކަށް ޑީފޯލްޓް ރަނަގޅުވާނެ. ވިންޑޯސް-ސްޓައިލްގެ ، ކޮމިޓް ޔުނިކްސް-ސްޓައިލް ލައިންގެ ނިންމުން ރަނގަޅު.

+ +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +[git-scm.com](https://git-scm.com/) ގިޓު ޑައުންލޯޑުކޮށްފައ އިރުޝާދުތައް ބަލާ. + +> **ނޯޓު** އޯއެސް އެކްސް 10.6، 10.7، ނުވަތަ 10.8 ބޭނުންކުރާނަމަ، ގިޓުގެ ވާރޝަން މިތަނުން ޑައުންލޯޑުކުރޭ:[Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/dv-MV/deploy/signup_pythonanywhere.md b/dv-MV/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..34ba026af22 --- /dev/null +++ b/dv-MV/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +ޕައިތަން އެނީވެއަރ އަކީ ކްލައުޑުގައި ވާ ސާރވާރތަކުގައި ޕައިތަން ކޯޑު ރަންކުރުމަށް ބޭނުންކުރާ ޚިދުމަތެއް. އަހަރެމެން ޕައިތަން އެނީވެއަރ ބޭނުންކުރާނީ ސައިޓު ހޮސްޓުކޮށް އިންޓަނެޓުގައި ލައިވްކުރުމަށް. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/dv-MV/django/README.md b/dv-MV/django/README.md new file mode 100644 index 00000000000..0f2c4ef30f6 --- /dev/null +++ b/dv-MV/django/README.md @@ -0,0 +1,27 @@ +# What is Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/dv-MV/django_admin/README.md b/dv-MV/django_admin/README.md new file mode 100644 index 00000000000..156eae05654 --- /dev/null +++ b/dv-MV/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/dv-MV/django_forms/README.md b/dv-MV/django_forms/README.md new file mode 100644 index 00000000000..68676f99fa5 --- /dev/null +++ b/dv-MV/django_forms/README.md @@ -0,0 +1,479 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Security + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/dv-MV/django_installation/README.md b/dv-MV/django_installation/README.md new file mode 100644 index 00000000000..9b024008342 --- /dev/null +++ b/dv-MV/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/dv-MV/django_installation/instructions.md b/dv-MV/django_installation/instructions.md new file mode 100644 index 00000000000..fc965146844 --- /dev/null +++ b/dv-MV/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/dv-MV/django_models/README.md b/dv-MV/django_models/README.md new file mode 100644 index 00000000000..f2a68a8727f --- /dev/null +++ b/dv-MV/django_models/README.md @@ -0,0 +1,201 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/dv-MV/django_orm/README.md b/dv-MV/django_orm/README.md new file mode 100644 index 00000000000..ffe309bd81e --- /dev/null +++ b/dv-MV/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/dv-MV/django_start_project/README.md b/dv-MV/django_start_project/README.md new file mode 100644 index 00000000000..3767c62e17f --- /dev/null +++ b/dv-MV/django_start_project/README.md @@ -0,0 +1,260 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/dv-MV/django_templates/README.md b/dv-MV/django_templates/README.md new file mode 100644 index 00000000000..db2d20c4d4e --- /dev/null +++ b/dv-MV/django_templates/README.md @@ -0,0 +1,108 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/dv-MV/django_urls/README.md b/dv-MV/django_urls/README.md new file mode 100644 index 00000000000..d37a5e3c2fd --- /dev/null +++ b/dv-MV/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/dv-MV/django_views/README.md b/dv-MV/django_views/README.md new file mode 100644 index 00000000000..ab271e0914f --- /dev/null +++ b/dv-MV/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/dv-MV/dynamic_data_in_templates/README.md b/dv-MV/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..5a6ef017adf --- /dev/null +++ b/dv-MV/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/dv-MV/extend_your_application/README.md b/dv-MV/extend_your_application/README.md new file mode 100644 index 00000000000..c70a2db97ff --- /dev/null +++ b/dv-MV/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/dv-MV/how_the_internet_works/README.md b/dv-MV/how_the_internet_works/README.md new file mode 100644 index 00000000000..7b2c014c292 --- /dev/null +++ b/dv-MV/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +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: + +![Figure 1.2](images/internet_3.png) + +It is fascinating, isn't it? But 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 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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - you send messages and you expect some response. 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 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, 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 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! \ No newline at end of file diff --git a/dv-MV/html/README.md b/dv-MV/html/README.md new file mode 100644 index 00000000000..27c81ea68be --- /dev/null +++ b/dv-MV/html/README.md @@ -0,0 +1,227 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is 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 `TemplateDoesNotExist`, try to restart your server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +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 line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to GitHub + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% 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. + +{% 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: + +{% 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 %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/dv-MV/installation/README.md b/dv-MV/installation/README.md new file mode 100644 index 00000000000..b97592acbe8 --- /dev/null +++ b/dv-MV/installation/README.md @@ -0,0 +1,68 @@ +# 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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. + +Good luck! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Installation + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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. \ No newline at end of file diff --git a/dv-MV/intro_to_command_line/README.md b/dv-MV/intro_to_command_line/README.md new file mode 100644 index 00000000000..b95191c95c8 --- /dev/null +++ b/dv-MV/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Your first command (YAY!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM
Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/dv-MV/intro_to_command_line/open_instructions.md b/dv-MV/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/dv-MV/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/dv-MV/python_installation/README.md b/dv-MV/python_installation/README.md new file mode 100644 index 00000000000..8470b71f1f4 --- /dev/null +++ b/dv-MV/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/dv-MV/python_installation/instructions.md b/dv-MV/python_installation/instructions.md new file mode 100644 index 00000000000..592aafe0b5d --- /dev/null +++ b/dv-MV/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 the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/dv-MV/python_introduction/README.md b/dv-MV/python_introduction/README.md new file mode 100644 index 00000000000..6b66f8b55c6 --- /dev/null +++ b/dv-MV/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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. + +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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, type the `exit()` function + +{% 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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/dv-MV/template_extending/README.md b/dv-MV/template_extending/README.md new file mode 100644 index 00000000000..7f3697b7fd4 --- /dev/null +++ b/dv-MV/template_extending/README.md @@ -0,0 +1,151 @@ +# Template extending + +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. + +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 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 + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/dv-MV/whats_next/README.md b/dv-MV/whats_next/README.md new file mode 100644 index 00000000000..97c41870d93 --- /dev/null +++ b/dv-MV/whats_next/README.md @@ -0,0 +1,43 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](https://twitter.com/djangogirls) to stay up to date. + +### Can you recommend any further resources? + +Yes! There are a *lot* of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. + +#### Django + +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS and JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! \ No newline at end of file diff --git a/el-GR/GLOSSARY.md b/el-GR/GLOSSARY.md new file mode 100644 index 00000000000..b1bce01c323 --- /dev/null +++ b/el-GR/GLOSSARY.md @@ -0,0 +1,3 @@ +# Επεξεργαστής Κώδικα + +Ο επεξεργαστής κώδικα είναι μια εφαρμογή που σου επιτρέπει να επεξεργάζεσαι και να αποθηκεύεις τον κώδικα σου, ώστε να είσαι σε θέση να επιστρέψεις σε αυτό αργότερα. Επίσης σου προσφέρει διάφορα εργαλεία όπως εύκολη αναζήτηση, αυτόματη συμπλήρωση κώδικα, απ' ευθείας μετάβαση σε κάποιο σημείο κλπ. Μπορείς να μάθεις πού μπορείς να βρείς ένα από το [κεφάλαιο επεξεργαστής κώδικα](./code_editor/README.md) \ No newline at end of file diff --git a/el-GR/README.md b/el-GR/README.md new file mode 100644 index 00000000000..c179ba84d8e --- /dev/null +++ b/el-GR/README.md @@ -0,0 +1,51 @@ +# Φροντιστήριο Django Girls + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> Αυτό το φροντιστήριο χορηγείται υπό την άδεια χρήσης με το όνομα: Creative Commons Attribution-ShareAlike 4.0 International License. Για να δείτε ένα αντίγραφο αυτής της άδειας χρήσης, επισκεφθείτε τον ακόλουθο σύνδεσμο https://creativecommons.org/licenses/by-sa/4.0/ + +## Καλώς ήρθατε + +Καλώς ήρθατε στο φροντιστήριο Django Girls! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Εισαγωγή + +Έχεις νιώσει ποτέ ότι ο κόσμος γίνεται όλο και περισσότερο σχετικός με την τεχνολογία και δεν μπορείς (ακόμα) να συσχετιθείς; Έχεις ποτέ αναρωτηθεί πώς να δημιουργήσεις μια ιστοσελίδα, αλλά ποτέ δεν είχες αρκετό κίνητρο για να ξεκινήσεις; Έχεις ποτέ σκεφτεί οτι ο κόσμος του software είναι πολύ περίπλοκος για σένα για να προσπαθήσεις να κάνεις κάτι από μόνη σου; + +Λοιπόν, έχουμε καλά νέα για σένα! Ο προγραμματισμός δεν είναι τόσο δύσκολος όσο φαίνεται και θέλουμε να σου δείξουμε πόσο διασκεδαστικός μπορεί να είναι. + +Αυτός ο οδηγός δεν θα σε μετατρέψει σε προγραμματιστή ως δια μαγείας. Αν θέλεις να γίνεις καλή προγραμματίστρια, χρειάζεται μήνες ή ακόμη και χρόνια εκμάθησης και πρακτικής εξάσκησης. Όμως θέλουμε να σου δείξουμε οτι ο προγραμματισμός ή η δημιουργία ιστιοσελίδων δεν είναι τόσο περίπλοκο όσο φαίνεται. Θα προσπαθήσουμε να σου εξηγήσουμε τα διάφορα κομμάτια όσο καλύτερα μπορούμε, ούτως ώστε να μην σε φοβίζει η τεχνολογία. + +Ελπίζουμε να μπορέσουμε να σε κάνουμε να αγαπήσεις την τεχνολογία, όπως εμείς! + +## Τι θα μάθεις κατα τη διάρκεια του οδηγού; + +Μόλις ολοκληρώσεις τον οδηγό, θα έχεις μία μικρή λειτουργική εφαρμογή ιστού (web application): το δικό σου blog. Θα σου δείξουμε πως να το ανεβάσεις ηλεκτρονικά, ώστε άλλοι να δουν την δουλειά σου! + +Θα φαίνεται έτσι (πάνω κάτω): + +![Σχήμα 0.1](images/application.png) + +> Αν είσαι μόνος σου χωρίς κάποιον να σε βοηθάει, τότε σε περίπτωση προβλήματος, έχουμε ένα σύστημα συνομιλίας για εσένα: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). Ζητήσαμε από τους προπονητές μας και τους προηγούμενους συμμετάσχοντες να είναι εκεί που και που και να βοηθάνε άλλους με το σεμινάριο! Μην φοβάστε να κάνετε ερωτήσεις εκεί! + +Οκ, [ ας ξεκινήσουμε από την αρχή...](./how_the_internet_works/README.md) + +## Ακολουθώντας τον οδηγό στο σπίτι + +Είναι εκπληκτικό να λάβετε μέρος στο εργαστήριο Django Girls, αλλά γνωρίζουμε ότι δεν είναι πάντα εφικτό να παρακολουθήσετε ένα. Για αυτό σας ενθαρρύνουμε να προσπαθήσετε να ακολουθήσετε αυτό το σεμινάριο στο σπίτι. Για τους αναγνώστες στο σπίτι, προς το παρόν ετοιμάζουμε βίντεο που θα το κάνουν ευκολότερο να παρακολουθήσετε τον οδηγό από μόνοι σας. Είναι ακόμα ένα έργο σε εξέλιξη, αλλά όλο και περισσότερα πράγματα θα καλυφθούν σύντομα στο κανάλι του YouTube [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed). + +Σε κάθε κεφάλαιο που έχει ήδη καλυφθεί, υπάρχει ένας σύνδεσμος που οδηγεί στο αντίστοιχο βίντεο. + +## Σχετικά με μας και πως να συνεισφέρετε + +Αυτό το σεμινάριο συντηρείται από την κοινότητα [DjangoGirls](https://djangogirls.org/). Εάν βρείτε τυχόν λάθη ή θέλετε να ενημερώσετε το φροντιστήριο παρακαλούμε [ακολουθήστε τις οδηγίες για συνεισφορά](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## Θα θέλατε να μας βοηθήσετε να μεταφράσετε τον οδηγό σε άλλες γλώσσες; + +Προς το παρόν, οι μεταφράσεις διατηρούνται στην πλατφόρμα του crowdin.com στο: + +https://crowdin.com/project/django-girls-tutorial + +Εάν η γλώσσα σας δεν είναι καταχωρημένη στο [crowdin](https://crowdin.com/), παρακαλούμε [ανοίξτε ένα νέο θέμα](https://github.com/DjangoGirls/tutorial/issues/new) ενημερώνοντας μας για την γλώσσα ώστε να την προσθέσουμε. \ No newline at end of file diff --git a/el-GR/SUMMARY.md b/el-GR/SUMMARY.md new file mode 100644 index 00000000000..71f57d59051 --- /dev/null +++ b/el-GR/SUMMARY.md @@ -0,0 +1,35 @@ +# Περίληψη + +* [Εισαγωγή](README.md) +* [Εγκατάσταση](installation/README.md) + * [Γραμμή Εντολών](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Επεξεργαστής Κώδικα](installation/README.md#code-editor) + * [Εικονικό Περιβάλλον](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Εγκατάσταση (chromebook)](chromebook_setup/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 project!](django_start_project/README.md) +* [Μοντέλα (models) του Django](django_models/README.md) +* [Διαχείριση μέσω Django admin](django_admin/README.md) +* [Ανεβάστε!](deploy/README.md) +* [Django URLs](django_urls/README.md) +* [Django views - ώρα να δημιουργήσετε!](django_views/README.md) +* [Εισαγωγή στην HTML](html/README.md) +* [Django ORM (Querysets)](django_orm/README.md) +* [Δυναμικά δεδομένα στα templates](dynamic_data_in_templates/README.md) +* [Django templates](django_templates/README.md) +* [CSS - κάντε το όμορφο](css/README.md) +* [Επεκτείνοντας τα templates](template_extending/README.md) +* [Επεκτείνοντας την εφαρμογή σας](extend_your_application/README.md) +* [Φόρμες Django](django_forms/README.md) +* [Τι υπάρχει μετά;](whats_next/README.md) \ No newline at end of file diff --git a/el-GR/chromebook_setup/README.md b/el-GR/chromebook_setup/README.md new file mode 100644 index 00000000000..f53690448d9 --- /dev/null +++ b/el-GR/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Ρυθμίσεις για χρήστες Chromebook + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/el-GR/chromebook_setup/instructions.md b/el-GR/chromebook_setup/instructions.md new file mode 100644 index 00000000000..988b083f74c --- /dev/null +++ b/el-GR/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Μπορείτε [ να παραλείψετε αυτή την ενότητα](http://tutorial.djangogirls.org/en/installation/#install-python) εάν δεν χρησιμοποιείτε το Chromebook. Εάν το χρησιμοποιείτε, η διαδικασία εγκατάστασης θα είναι λίγο διαφορετική. Σε αυτή την περίπτωση μπορείτε να αγνοήσετε τις υπόλοιπες οδηγίες εγκατάστασης. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Το CloudIDE είναι ένα εργαλείο το οποίο σου παρέχει έναν επεξεργαστή κώδικα καθώς και πρόσβαση σε έναν υπολογιστή στο internet στον οποίο μπορείς να εγκαταστήσεις, να γράψεις και να τρέξεις το λογισμικό. Κατά τη διάρκεια του οδηγού, το CloudIDE θα παίζει το ρόλο του *local machine* (δηλαδή του τοπικού υπολογιστή σας). Παραταύτα, θα χρειαστεί να γράφετε εντολές στο τερματικό όπως ακριβώς οι συμμαθητές σας που χρησιμοποιούν OS X, Ubuntu ή Windows, με την μόνη διαφορά ότι το τερματικό δεν θα τρέχει στον υπολογιστή που κάθεστε αλλά στο cloud (σύννεφο), εκεί που το όρισε το CloudIDE (σε κάποιον εικονικό υπολογιστή, δηλαδή, στο internet). Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). Μπορείτε να επιλέξετε ένα από τα cloud IDEs και να ακολουθήσετε τις αντίστοιχες οδηγίες του. + +#### PaizaCloud Cloud IDE + +1. Πηγαίνετε στο [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Δημιούργησε λογαριασμό +3. Click *New Server* and choose the Django app +4. Κάντε κλικ στο κουμπί Terminal (στην αριστερή πλευρά του παραθύρου) + +Τώρα θα πρέπει να δείτε μια σελίδα με πλαϊνή μπάρα εργασίων και κουμπιά στα αριστερά. Κάντε κλικ στο κουμπί «Terminal» για να ανοίξετε το παράθυρο του τερματικού (ή αλλιώς "κοσνόλα" ή "γραμμή εντολών") όπως παρακάτω: + +{% filename %}Terminal{% endfilename %} + + $ + + +Το τερματικό στο PaizaCloud Cloud IDE είναι έτοιμο να δεχτεί τις εντολές σας. Μπορείτε να αλλάξετε το μέγεθος του παραθύρου ή να το μεγιστοποιήσετε, αν θέλετε. + +#### AWS Cloud9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + yourusername:~/workspace $ + + +Αυτή η κάτω περιοχή είναι το τερματικό σας. Μπορείτε να χρησιμοποιήσετε το τερματικό για να στείλετε οδηγίες στον απομακρυσμένο υπολογιστή Cloud 9. Μπορείτε να αλλάξετε το μέγεθος αυτού του παραθύρου για να το κάνετε μεγαλύτερο. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### Εικονικό Περιβάλλον + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/el-GR/code_editor/README.md b/el-GR/code_editor/README.md new file mode 100644 index 00000000000..063b14ea2e9 --- /dev/null +++ b/el-GR/code_editor/README.md @@ -0,0 +1,11 @@ +# Προγράμματα Επεξεργασίας Κώδικα + +> Για τους αναγνώστες στο σπίτι: αυτό το κεφάλαιο καλύπτεται στο [ Εγκαθιστώντας την Python& Πρόγραμμα επεξεργασίας κώδικα](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s)βίντεο. + +Σύντομα πρόκειται να γράψετε την πρώτη σας γραμμή κώδικα, οπότε ήρθε η ώρα να κατεβάσετε ένα πρόγραμμα επεξεργασίας κώδικα (code editor)! + +> **Σημείωση** εάν χρησιμοποιείτε Chromebook, παρακάμψτε αυτό το κεφάλαιο και σιγουρευτείτε ότι ακολουθείτε τις οδηγίες [Εγκατάστασης Chromebook](../chromebook_setup/README.md). Η επιλογή σας ως προς το cloud IDE (PaizaCloud cloud IDE ή AWS Cloud9) περιλαμβάνει ήδη ένα πρόγραμμα επεξεργασίας κώδικα και όταν ανοίγετε ένα αρχείο στο IDE σας από το μενού "Αρχείο", θα χρησιμοποιείτε αυτόματα εκείνον τον επεξεργαστή. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/el-GR/code_editor/instructions.md b/el-GR/code_editor/instructions.md new file mode 100644 index 00000000000..eea5b05f839 --- /dev/null +++ b/el-GR/code_editor/instructions.md @@ -0,0 +1,37 @@ +Υπάρχουν πολλά code editors (επεξεργαστές κώδικα) διαθέσιμοι και για αυτό είστε ελεύθεροι να διαλέξετε αυτόν που σας αρέσει περισσότερο (ή ανάλογα την τσέπη σας αν θέλετε να αγοράσετε κάποιον). Οι περισσότεροι προγραμματιστές της Python χρησιμοποιούν περίπλοκα, αλλά εξαιρετικά ισχυρά IDEs (Integrated Development Environments - Ολοκληρωμένα Περιβάλλοντα Ανάπτυξης), όπως το PyCharm. Για αρχάριους, ωστόσο, αυτή η επιλογή είναι ίσως η λιγότερο κατάλληλη· για αυτό σας προτείνουμε προγράμματα εξίσου ισχυρά, αλλά πολύ απλούστερα. + +Οι προτάσεις μας φαίνονται παρακάτω αλλά μην διστάσεις να ρωτήσεις τον "coach" (εκπαιδευτή) σου ποιες είναι οι προτιμήσεις του. Θα είναι ευκολότερο αργότερα να σε βοηθήσει σε όποιο ζήτημα μπορεί να προκύψει. + +## Visual Studio Code + +Το Visual Studio Code είναι ένας κειμενογράφος κώδικα που αναπτύσσεται απ' τη Microsoft για Windows, Linux και macOS. Περιλαμβάνει υποστήριξη για αποσφαλμάτωση, ενσωματωμένο έλεγχο για το Git, χρωματική απεικόνιση του κώδικα, έξυπνη αυτόματη συμπλήρωση του κώδικα, κλπ. + +[Κατεβάστε το εδώ](https://code.visualstudio.com/) + +## Gedit + +Το Gedit είναι ένας ανοιχτού κώδικα, ελεύθερος κειμενογράφος, διαθέσιμος για όλα τα λειτουργικά συστήματα. + +[Κατεβάστε το εδώ](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Το Sublime Text είναι ένας πολύ δημοφιλής κειμενογράφος με δωρεάν δοκιμαστική περίοδο και διατίθεται για όλα τα λειτουργικά συστήματα. + +[Κατεβάστε το εδώ](https://www.sublimetext.com/3) + +## Atom + +Το Atom είναι άλλος ένας δημοφιλής κειμενογράφος. Είναι δωρεάν, ανοιχτού κώδικα και διαθέσιμος για Windows, OS X και Linux. Το Atom αναπτύσσεται από το [GitHub](https://github.com/). + +[Κατεβάστε το εδώ](https://atom.io/) + +## Γιατί χρειαζόμαστε τους code editors (Προγράμματα Επεξεργασίας Κώδικα); + +Μπορεί να αναρωτιέσαι γιατί χρειάζεται να εγκαταστήσουμε κάποιο ειδικό πρόγραμμα επεξεργασίας κώδικα λογισμικού, αντί να χρησιμοποιήσουμε κάτι σαν το Word ή το Notepad. + +Ο πρώτος λόγος είναι ότι ο κώδικας πρέπει να είναι **απλό κείμενο** (δίχως bold, italic, πίνακες, εικόνες κλπ, όπως θα χρησιμοποιούσε κανείς σε έναν κοινό επεξεργαστή κειμένου). Το πρόβλημα με τα προγράμματα όπως το Word και το Textedit είναι ότι δεν παράγουν στην ουσία απλό κείμενο αλλά "πλούσιο" (με γραμματοσειρές, φορμάρισμα κειμένου και αυτά που αναφέραμε παραπάνω), χρησιμοποιώντας σύνθετες μορφές όπως το [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +Δεύτερον, τα προγράμματα επεξεργασίας κώδικα είναι ειδικά σχεδιασμένα για την σύνταξη κώδικα, ούτως ώστε να μπορούν να παρέχουν χρήσιμα εργαλεία όπως η επισήμανση του κώδικα με διαφορετικό χρώμα ανάλογα την σημασία του, το αυτόματο κλείσιμο εισαγωγικών κλπ. + +Θα τα δούμε όλα αυτά στην πράξη αργότερα. Σύντομα, θα αρχίσετε να βλέπετε τον παλιό σας, έμπιστο επεξεργαστή κώδικα ως ένα από τα αγαπημένα σας εργαλεία. :) \ No newline at end of file diff --git a/el-GR/css/README.md b/el-GR/css/README.md new file mode 100644 index 00000000000..2d8d4322c51 --- /dev/null +++ b/el-GR/css/README.md @@ -0,0 +1,330 @@ +# CSS - κάντε το όμορφο! + +Το blog μας φαίνεται αρκετά άσχημο, έτσι δεν είναι; Ωρα να το κάνουμε όμορφο! Γι'αυτή τη δουλειά θα χρειαστούμε το CSS. + +## Τι είναι το CSS; + +Το CSS (Cascading Style Sheets - Διαδοχικά Φύλλα Στυλ) είναι μια γλώσσα που χρησιμοποιείται για να περιγράψει την εμφάνιση και την μορφοποίηση μιας ιστοσελίδας που έχει γραφτεί σε γλώσσα σήμανσης (όπως η HTML). Δείτε το σαν το μακιγιάζ για την ιστοσελίδα μας ;) + +Άλλα δεν θέλουμε να ξεκινήσουμε από την αρχή ξανά, έτσι; Για ακόμα μια φορά θα χρησιμοποιήσουμε κάτι που οι προγραμματιστές χρησιμοποιούν ήδη και είναι δωρεάν στο διαδίκτυο. Το να ανακαλύπτουμε τον τροχό δεν έχει πλάκα, ξέρετε. + +## Ας χρησιμοποιήσουμε το Bootstrap! + +Το Bootstrap είναι μια από τις πιο δημοφιλή HTML / CSS εργαλειοθήκες (framework) που αποσκοπούν στην εύκολη και γρήγορη ανάπτυξη όμορφων ιστοσελίδων: https://getbootstrap.com/ + +Γράφτηκε από προγραμματιστές που εργάστηκαν στο Twitter. Τώρα αναπτύσσεται από εθελοντές από ολόκληρο το κόσμο! + +## Εγκατάσταση του Bootstrap + +Για την εγκατάσταση του Bootstrap, ανοίξτε το αρχείο `.html` στον επεξεργαστή κώδικα και προσθέστε αυτό στην ενότητα ``: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Αυτό δεν προσθέτει κάποια αρχεία στο project σας. Απλώς, δείχνει σε αρχεία που υπάρχουν στο διαδίκτυο. Πηγαίνετε, λοιπόν, επισκεφτείτε την ιστοσελίδα σας και ανανεώστε τη σελίδα. Νάτο! + +![Σχήμα 14.1](images/bootstrap1.png) + +Δείχνει ήδη πολύ καλύτερο! + +## Στατικά αρχεία στο Django + +Τέλος, ας ρίξουμε μια πιο προσεκτική ματιά στα λεγόμενα **στατικά αρχεία**. Τα στατικά αρχεία (static files) είναι όλα τα αρχεία CSS και όλα τα αρχεία εικόνας (φωτογραφίες). Το περιεχόμενο τους δεν εξαρτάται από το εκάστοτε request και έτσι μένει ίδιο για κάθε χρήστη. + +### Πού να τοποθετήσετε τα στατικά αρχεία στο Django + +Το Django ήδη ξέρει πού να βρει τα στατικά αρχεία για την ενσωματωμένη εφαρμογή «admin». Τώρα πρέπει να προσθέσουμε κάποια στατικά αρχεία για την δική μας εφαρμογή, `blog`. + +Για να το κάνουμε αυτό πρέπει να δημιουργήσουμε ένα φάκελο με το όνομα `static` μέσα στο φάκελο blog της εφαρμογής μας: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │   └── templates + └── mysite + + +Το Django θα βρίσκει αυτόματα οποιοδήποτε φάκελο ονομάζεται "static" μέσα στους φακέλους οποιασδήποτε εφαρμογή σας. Έπειτα θα μπορεί να χρησιμοποιεί το περιεχόμενο τους ως στατικά αρχεία. + +## Το πρώτο CSS αρχείο σας! + +Ας δημιουργήσουμε ένα CSS αρχείο τώρα, για να προσθέσετε το δικό σας στυλ στην ιστοσελίδα σας. Δημιουργήστε έναν νέο φάκελο που ονομάζεται `css` μέσα στο `static` φάκελο. Στη συνέχεια, δημιουργήστε ένα νέο αρχείο που ονομάζεται `blog.css` μέσα σε αυτόν τον φάκελο `css`. Είστε έτοιμοι; + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +Ώρα να γράψουμε λίγο CSS! Άνοιξτε το αρχείο `blog/static/css/blog.css` στον επεξεργαστή. + +Δεν θα εμβαθύνουμε πολύ σχετικά με την γλώσσα CSS. Υπάρχει μια πρόταση σχετικά με μάθημα CSS στο τέλος αυτής της σελίδας αν θέλετε να μάθετε περισσότερα. + +Αλλά ας δοκιμάσουμε μερικά πράγματα. Ίσως θα μπορούσαμε να αλλάξουμε το χρώμα των τίτλων της σελίδας μας; Για να καταλάβετε τη λογική των χρωμάτων, οι υπολογιστές χρησιμοποιούν ειδικούς κώδικες. Αυτοί οι κώδικες ξεκινάνε με `#` και ακολουθούνται από 6 γράμματα (A-F) και αριθμούς (0-9). Για παράδειγμα, ο κωδικός για το μπλε είναι `#0000FF`. Μπορείτε να βρείτε τους κωδικούς των χρωμάτων για πολλά χρώματα εδώ: http://www.colorpicker.com/. Μπορείτε επίσης να χρησιμοποιήσετε [προκαθορισμένα χρώματα](http://www.w3schools.com/colors/colors_names.asp) με το αγγλικό όνομά τους, όπως το `red` (κόκκινο) και το `green` (πράσινο). + +Στο αρχείο `blog/static/css/blog.css` πρέπει να προσθέσετε τον παρακάτω κώδικα: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +Το `h1 a` είναι ένας επιλογέας CSS (CSS selector). Αυτό σημαίνει ότι θέλουμε να εφαρμόσουμε τα στυλ (στη συγκεκριμένη περίπτωση έχουμε ένα στυλ, το χρώμα) σε κάθε `a` στοιχείο μέσα σε κάθε `h1` στοιχείο. Ο επιλογέας `h2 a` κάνει το ίδιο πράγμα αλλά για τα `h2` στοιχεία. Έτσι όταν έχουμε κάτι σαν `

σύνδεσμο

`, το `h1 a ` στυλ θα εφαρμοστεί. Σε αυτή τη περίπτωση, του λέμε να αλλάξει το χρώμα του σε `#C25100`, που είναι το σκούρο πορτοκαλί. Ή μπορείτε να βάλετε το δικό σας χρώμα εδώ, αλλά σιγουρευτείτε ότι έχει καλή αντίθεση σε λευκό φόντο! + +Μέσα σε ενα αρχείο CSS καθορίζουμε τα στύλ για τα στοιχεία μέσα στο HTML αρχείο. Ο πρώτος τρόπος που αναγνωρίζουμε στοιχεία είναι με το όνομα στοιχείου. Μπορεί να τα θυμάστε αυτά ως ετικέτες από την HTML. Πράγματα όπως `a`, `h1` και το `body` είναι όλα τα παραδείγματα των ονομάτων στοιχείων (HTML elements). Μπορούμε επίσης να προσδιορίσουμε στοιχεία από το χαρακτηριστικό `class` ή το χαρακτηριστικό `id`. Η τάξη (class) και η ταυτότητα (id) είναι ονόματα που δίνεις εσύ στο κάθε στοιχείο. Οι τάξεις αναφέρονται σε ομάδες στοιχείων και οι ταυτότητες σε συγκεκριμένα στοιχεία. For example, you could identify the following element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +Διαβάστε περισσότερα για τους επιλογείς CSS στο [w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +Στη συνέχεια, πρέπει να πούμε στο HTML αρχείο οτι θέλουμε να συμπεριλάβουμε αρχείο/α CSS. Ανοίξτε το αρχείο `blog/templates/blog/post_list.html` και προσθέστε αυτή τη γραμμή στην αρχή: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +Απλά "φορτώνουμε" στατικά αρχεία σε αυτό το σημείο :) Μεταξύ του `` και `` ετικετών (tags), μετά τα links με τα Bootstrap αρχεία CSS, προσθέστε αυτή τη γραμμή: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Ο browser διαβάζει τα αρχεία με την σειρά που δίνονται, οπότε πρέπει να σιγουρευτούμε ότι αυτή είναι η σωστή θέση. Διαφορετικά ο κώδικας στο αρχείο μας μπορεί να παρακαμφθεί από τον κώδικα στα αρχεία Bootstrap. Μόλις είπαμε στο template μας που βρίσκεται το CSS αρχείο μας. + +Το αρχείο σας πρέπει τώρα να μοιάζει κάπως έτσι: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +Εντάξει, αποθηκεύστε το αρχείο και ανανεώστε τη σελίδα! + +![Σχήμα 14.2](images/color2.png) + +Πολύ καλά! Θα θέλατε να δώσουμε λίγο αέρα στην ιστοσελίδα μας και να αυξήσουμε το περιθώριο στα αριστερά; Ας το δοκιμάσουμε! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +Προσθέστε αυτό στο CSS σας, αποθηκεύστε τον αρχείο και δείτε πως λειτουργεί! + +![Σχήμα 14.3](images/margin2.png) + +'Ισως μπορούμε να αλλάξουμε την γραμματοσειρά της επικεφαλίδας μας. Μεσα στο `` που βρίσκεται μεσα στο αρχείο `blog/templates/blog/post_list.html` βάλτε αυτό: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Όπως πριν, ελέγξτε τη σειρά και τοποθετήστε το πριν τον σύνδεσμο `blog/static/css/blog.css`. Αυτή η γραμμή θα εισάγει μια γραμματοσειρά που λέγεται *Lobster* από τα Google Fonts (https://www.google.com/fonts). + +Βρείτε το `h1 a` μπλοκ (τον κώδικα μεταξύ `{` και `}`) μέσα στο αρχείο CSS `blog/static/css/blog.css`. Τώρα προσθέστε την γραμμή `font-family: 'Lobster';` μεταξύ των αγκύλων και ανανεώστε τη σελίδα: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Σχήμα 14.3](images/font.png) + +Τέλεια! + +Όπως αναφέρθηκε παραπάνω, το CSS έχει την έννοια των κλάσεων (classes). Αυτές σας επιτρέπουν να ονομάσετε ένα μέρος του κώδικα HTML και να εφαρμόσετε στυλ μόνο σε αυτό το μέρος, χωρίς να επηρεάσετε άλλα μέρη. Αυτό μπορεί να είναι εξαιρετικά χρήσιμο! Ίσως να έχετε δύο divs τα οποία περιγράφουν κάτι διαφορετικό το καθένα (όπως πχ μια επικεφαλίδα και ένα post). Μια class μπορεί να σας βοηθήσει να τα κάνετε να μοιάζουν διαφορετικά. + +Go ahead and name some parts of the HTML code. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Τώρα θα προσθέσουμε κώδικα στους επιλογείς (selectors) που μόλις δημιουργήσαμε. Οι επιλογείς που ξεκινούν με `.` αναφέρονται σε κλάσεις. Υπάρχουν πολλοί σπουδαίοι οδηγοί (tutorials) και εξηγήσεις σχετικά με το CSS στο διαδίκτυο τα οποία θα σας βοηθήσουν να καταλάβετε τον παρακάτω κώδικα. Για αρχή, αντιγράψτε το στο αρχείο `blog/static/css/blog.css`: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Μετά, περιβάλλετε τον κώδικα HTML που προβάλει τα posts με κλάσεις. Αντικατάστησε αυτό: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +μέσα στο αρχείο `blog/templates/blog/post_list.html` με αυτό: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Αποθήκευσε τα αρχεία και ανανέωστε την ιστοσελίδα σας. + +![Σχήμα 14.4](images/final.png) + +Ουάου! Φαίνεται τέλειο, έτσι δεν είναι; Κοιτάξτε τον κώδικα που μόλις κάναμε επικόλληση για να βρείτε τα σημεία που προσθέσαμε κλάσεις στην HTML και τις χρησιμοποιήσαμε στο CSS. Που θα κάνατε την αλλαγή αν θέλατε την ημερομηνία να είναι τιρκουάζ; + +Μην φοβάστε να πειραματιστείτε με το CSS λίγο και να προσπαθήσετε να αλλάξετε μερικά πράγματα. Παίζοντας με το CSS μπορεί να σε κάνει να καταλάβεις τι κάνουν τα διάφορα πράγματα. Εάν κάτι πάει στραβά μην ανησυχείτε - μπορείτε πάντα να το αναιρέσετε! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Είστε έτοιμοι για το επόμενο κεφάλαιο; :) \ No newline at end of file diff --git a/el-GR/deploy/README.md b/el-GR/deploy/README.md new file mode 100644 index 00000000000..b6b1194c7a1 --- /dev/null +++ b/el-GR/deploy/README.md @@ -0,0 +1,246 @@ +# Ανεβάστε! + +> **Σημείωση** Το ακόλουθο κεφάλαιο μπορεί να είναι μερικές φορές λίγο δύσκολο να ολοκληρωθεί. Επιμένετε και τελειώστε το, το ανέβασμα είναι ένα σημαντικό μέρος της διαδικασίας ανάπτυξης της ιστοσελίδας. Άλλωστε όταν αναπτύσετε ένα website θα θέλατε στο τέλος να το δει όλος ο κόσμος, όχι μόνο εσείς στον υπολογιστή σας. Το κεφάλαιο αυτό τοποθετείται στη μέση του οδηγού, έτσι ώστε ο μέντορας σας να μπορεί να σας βοηθήσει με την περίπλοκη διαδικασία του "ανεβάσματος" της ιστοσελίδας στο διαδίκτυο. Αυτό σημαίνει ότι μπορείτε ακόμη να ολοκληρώσετε τον οδηγό μόνοι σας ακόμα και αν σας τελειώσει ο χρόνος. + +Μέχρι τώρα, η ιστοσελίδα σου ήταν μόνο διαθέσιμη στον υπολογιστή σου. Τώρα θα μάθεις πως να την ανεβάσεις σε κάποιον server! "Ανεβάζω στο server" (ή άλλιώς deploy) είναι η διαδικασία της δημοσίευσης την εφαρμογής σας στο διαδίκτυο, έτσι ώστε οι άνθρωποι τελικά να πάνε και να δουν την εφαρμογή σας (μέσα από κάποιο url, πχ https://www.mypage. gr). :) + +Όπως μάθατε, μια ιστοσελίδα πρέπει να βρίσκεται σε ένα διακομιστή (server). Υπάρχουν εκατοντάδες υπηρεσίες διακομιστών (server providers) εκεί έξω. Εμείς θα χρησιμοποιήσουμε το [PythonAnywhere](https://www.pythonanywhere.com/). Το PythonAnywhere είναι δωρεάν για μικρές εφαρμογές που δεν έχουν πολλούς επισκέπτες, καθιστώντας το ιδανικό για την περίπτωση μας. + +Η άλλη υπηρεσία που θα χρησιμοποιήσουμε είναι το [GitHub](https://www.github.com), το οποίο είναι μια υπηρεσία φιλοξενίας κώδικα. Υπάρχουν και άλλες υπηρεσίες φιλοξενίας κώδικα εκεί έξω (όπως το BitBucket και άλλες), αλλά σχεδόν όλοι οι προγραμματιστές έχουν λογαριασμό GitHub αυτές τις μέρες όπως και εσείς τώρα! + +Αυτά τα τρία μέρη θα είναι σημαντικά για εσάς. Ο τοπικός σας υπολογιστής θα είναι το μέρος όπου θα κάνετε ανάπτυξη και δοκιμή. Όταν είστε ικανοποιημένοι με τις αλλαγές, θα τοποθετήσετε ένα αντίγραφο του προγράμματος σας στο GitHub. Η ιστοσελίδα σας θα είναι στο PythonAnywhere και θα την ενημερώσετε με το να πάρετε ένα καινούριο αντίγραφο του κωδικού σας από το GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Ξεκινώντας με το Git repo + +Το Git παρακολουθεί τις αλλαγές σε ένα συγκεκριμένο σύνολο αρχείων που αποκαλείται αρχείο αποθήκευσης κώδικα (ή «repo» εν συντομία, όπως είπαμε παραπάνω). Ας δημιουργήσουμε ένα για την εφαρμογή μας. Ανοίξτε την κονσόλα σας, μεταβείτε στον φάκελο`djangogirls` και εκτελέστε αυτές τις εντολές: + +> **Σημείωση** Ελέγξτε που βρίσκεστε στην κονσόλα (δηλαδή σε ποιον φάκελο) με την εντολή `pwd` (Mac OS X/Linux) ή `cd` (Windows) πριν αρχικοποιήσετε το repo σας. Θα πρέπει να βρίσκεστε στο φάκελο `djangogirls`. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Η αρχικοποίηση του repo είναι κάτι που πρέπει να γίνεται μόνο μια φορά ανά project (δίχως να χρειάζεται να εισάγετε το όνομα χρήστη και το email σας, ποτέ ξανά). + +Το Git θα παρακολουθήσει τις αλλαγές σε όλα τα αρχεία και τους φακέλους σε αυτόν τον φάκελο (σε αυτό το project). Ωστόσο υπάρχουν ορισμένα αρχεία που θέλουμε να τα αγνοήσει και να μην συμπεριληφθούν στο repo. Το κάνουμε αυτό δημιουργώντας ένα αρχείο που ονομάζεται `.gitignore` στον αρχικό φάκελο. Ανοίξτε το πρόγραμμα επεξεργασίας κειμένου και δημιουργήστε ένα νέο αρχείο με το ακόλουθο περιεχόμενο: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +Αποθηκεύστε το ως `.gitignore` μέσα στον φάκελο "djangogirls". + +> **Σημείωση** Η τελεία στην αρχή του ονόματος του αρχείου είναι σημαντική! Αν έχετε κάποιο πρόβλημα στη δημιουργία του (στο Finder, για παράδειγμα, των Mac υπολογιστών, δεν αρέσει να δημιουργούνται αρχεία με την τελεία ως πρώτο χαρακτήρα), τότε χρησιμοποιήστε το "Αποθήκευση ως...". Σιγουρευτείτε, πάντως, να μην προσθέσετε `.txt`, `.py`, ή οποιοδήποτε άλλη κατάληξη στο όνομα του αρχείου. Θα αναγνωριστεί από το Git μόνο αν το όνομα του είναι ακριβώς `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Σημείωση** Ένα από τα ονόματα αρχείων που συμπεριλάβατε στο αρχείο `.gitignore` είναι το αρχείο `db.sqlite3`. Αυτό το αρχείο είναι μια τοπική βάση δεδομένων (database), όπου όλοι οι χρήστες και τα posts σας είναι αποθηκευμένα. Ακολουθούμε μια κοινή πρακτική όσον αφορά τον προγραμματισμό ιστού (web programming) η οποία απαιτεί την χρήση ξεχωριστής βάσης δεδομένων τοπικά στον υπολογιστή μας και στον server όπου θα ανεβάσουμε την εφαρμογή μας (PythonAnywhere). Η βάση δεδομένων του PythonAnywhere θα μπορούσε να είναι και αυτή SQLite, όπως στον υπολογιστή σας αλλά συχνά θα χρησιμοποιείτε μια πιο ευρέως διαδεδομένη και εμπλουτισμένη με πιο πολλά χαρακτηριστικά και δυνατότητες όπως η PostgresQL ή η MySQL. Όπως και να 'χει, μη συμπεριλαμβάνοντας την SQLite βάση στο repo, σημαίνει ότι όλα τα posts και οι χρήστες που δημιουργήσατε μέχρι τώρα θα είναι διαθέσιμα τοπικά στον υπολογιστή σας και θα χρειαστεί να τα ξαναδημιουργήσετε όταν ανεβάσετε το project σας. Να σκέφτεστε την τοπική βάση δεδομένων σας ως ένα παιδότοπο όπου μπορείτε να δοκιμάσετε διαφορετικά πράγματα και να μην φοβάστε ότι πρόκειται να διαγράψετε τις αληθινές σας δημοσιεύσεις από το blog σας. + +Είναι καλή ιδέα να χρησιμοποιήσετε την εντολή `git status` πριν από την εντολή`git add` ή όποτε δεν είστε βέβαιοι για το τι έχει αλλάξει. Αυτό θα βοηθήσει να αποτραπούν οποιεσδήποτε εκπλήξεις, όπως το να προστεθούν ή να αποθηκευτούν λανθασμένα αρχεία. Η εντολή `git status` επιστρέφει πληροφορίες σχετικά με το ποια αρχεία είναι untracked/modified/staged files, το status του branch και πολλές ακόμη πληροφορίες. Η έξοδος πρέπει να είναι παρόμοια με τα ακόλουθα: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +Και τέλος αποθηκεύουμε τις αλλαγές μας. Πηγαίνετε στην κονσόλα σας και εκτελέστε αυτές τις εντολές: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ 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 + +Πηγαίνετε στο [https://github.com](https://www.github.com) και δημιουργήστε έναν δωρεάν λογαριασμό. (Αν το έχετε ήδη κάνει αυτό, τέλεια!). Σιγουρευτείτε ότι θυμάστε τον κωδικό πρόσβασης σας (προσθέστε τον σε κάποιον διαχειριστή κωδικών πρόσβασης, αν έχετε κάποιον). + +Έπειτα, δημιουργήστε ένα νέο repo, δίνοντας του το όνομα "my-first-blog". Αφήστε το κουτάκι "initialize with a README" κενό. Αφήστε, επίσης την επιλογή .gitignore κενή (το έχουμε ήδη αυτό το αρχείο) και τέλος αφήστε το License ως None. + +![](images/new_github_repo.png) + +> **Σημείωση** Το όνομα `my-first-blog` είναι σημαντικό. Θα μπορούσατε να διαλέξετε ένα άλλο, αλλά επειδή θα το χρησιμοποιείτε αρκετά στις ακόλουθες εντολές, καλό να είναι χρησιμοποιήσετε το ίδιο εκτός και αν είστε λάτρης του πληκτρολογίου και σας αρέσει να γράφετε! Είναι πιο εύκολο να μείνετε με το όνομα `my-first-blog`. + +Στην επόμενη οθόνη θα δείτε το url (την διεύθυνση) του repo σας την οποία θα χρησιμοποιήσουμε παρακάτω: + +![](images/github_get_repo_url_screenshot.png) + +Τώρα το μόνο που μένει είναι να συνδέσουμε το τοπικό repo μας με το remote (απομακρυσμένο). + +Πληκτρολογήστε τα ακόλουθα στην κονσόλα σας (αντικαταστήστε το `` με το όνομα χρήστη σας στο GitHub αλλά χωρίς τα "<>". Το url θα πρέπει να είναι το ίδιο με το url που είδατε πριν: + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Όταν ανεβάζετε στο GitHub, θα ερωτηθείτε για το όνομα χρήστη και τον κωδικό πρόσβασης σας (είτε μέσω κονσόλας είτε μέσω ενός χωριστού παράθυρου). Αφού τα εισάγετε, θα δείτε κάτι σαν το παρακάτω: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Ο κώδικας σας είναι πλέον στο GitHub. Πηγαίνετε να τον δείτε! Θα διαπιστώσετε ότι και άλλο δημοφιλή ανοιχτού λογισμικού projects φιλοξενούνται στο GitHub, όπως το ίδιο το [Django](https://github.com/django/django), το [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial) και άλλα πολλά. :) + +# Ανεβάζοντας το blog μας στο PythonAnywhere + +## Δημιουργήστε έναν δωρεάν λογαριασμό στο PythonAnywhere + +> **Σημείωση** Αν έχετε δημιουργήσει ήδη έναν τότε παραλείψτε αυτό το βήμα. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Παραμετροποιώντας το site μας στο PythonAnywhere + +Μεταβείτε πίσω στο [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) κλικάροντας στο logo και επιλέξτε να εκκινήσετε μια κονσόλα "Bash". Αυτή είναι η έκδοση της κονσόλας του PythonAnywhere σαν και αυτή που έχετε στον υπολογιστή σας. + +![Η ενότητα 'New Console' στο PythonAnywhere με ένα κουμπί για το 'bash'](images/pythonanywhere_bash_console.png) + +> **Σημείωση** Το PythonAnywhere είναι βασισμένο στο Linux, οπότε αν τρέχετε Windows, η κονσόλα ίσως να σας φανεί διαφορετική από αυτή που έχετε συνηθίσει. + +Η διαδικασία του ανεβάσματος της εφαρμογή σας (το blog) στο PythonAnywhere περιλαμβάνει τα εξής βήματα: το PythonAnywhere να μπορεί να "διαβάσει" τον κώδικα σας στο GitHub, να τον "κατεβάσει" και να τον αποθηκεύσει σε κάποιον από τους σκληρούς του δίσκους (pull) και στο τέλος να κάνει serve την εφαρμογή αυτή. Υπάρχουν οι χειροκίνητοι τρόποι για να επιτευχθούν αυτά τα βήματα αλλά το PythonAnywhere προσφέρει εργαλεία για αυτόν ακριβώς το λόγο. Ας το εγκαταστήσουμε πρώτα: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +Αυτό θα εμφανίσει κάτι σαν `Collecting pythonanywhere` και στο τέλος θα τελειώσει με μια γραμμή η οποία θα λέει `Successfully installed (...) pythonanywhere- (...)`. + +Τώρα θα τρέξουμε το βοηθητικό εργαλείο ούτως ώστε να παραμετροποιήσει την εφαρμογή μας από το GitHub. Πληκτρολογήστε τα ακόλουθα στην κονσόλα του PythonAnywhere (μην ξεχάσετε να χρησιμοποιήσετε αντί του `` το όνομα χρήστη σας του GitHub ούτως ώστε τα urls να είναι τα ίδια): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +Μπορείτε να βλέπετε τι γίνεται καθώς το πρόγραμμα τρέχει: + +- Κατεβάζει τον κώδικα σας από το GitHub +- Δημιουργεί ένα virtualenv στο PythonAnywhere όπως ακριβώς αυτό στον υπολογιστή σας +- Εμπλουτίζει το αρχείο settings.py με κάποιες ρυθμίσεις για το deployment +- Ρυθμίζει τη βάση δεδομένων στο PythonAnywhere χρησιμοποιώντας την εντολή `manage.py migrate` +- Ρυθμίζει τα στατικά αρχεία (θα μάθουμε γι'αυτά αργότερα) +- Τέλος ρυθμίζει το PythonAnywhere για να εξυπηρετήσει την εφαρμογή σας + +Παρόλο που στο PythonAnywhere όλα αυτά τα βήματα είναι αυτοματοποιημένα, όλα αυτά δεν αλλάζουν αν επιλέξετε κάποιον άλλον server provider. + +Αυτό που πρέπει να τονίσουμε είναι ότι η βάση δεδομένων στο PythonAnywhere είναι διαφορετική από αυτήν στον υπολογιστή σας. Ως αποτέλεσμα αυτού, θα χρειαστεί να αρχικοποιήσουμε τον λογαριασμό διαχειριστή με την εντολή `createsuperuser`. Το PythonAnywhere έχει ενεργοποιήσει το virtualenv για σας, οπότε το μόνο που μένει είναι να τρέξουμε: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Εισάγετε τα στοιχεία του χρήστη admin. Καλό είναι να χρησιμοποιήσετε τα ίδια με αυτά στον τοπικό υπολογιστή σας για να μην μπερδεύεστε εκτός και αν θέλετε να κάνετε να φτιάξετε ένα πιο ρεαλιστικό σενάριο όπου ο κωδικός αυτός θα πρέπει να είναι πιο δύσκολος ως προς την μαντεψιά. + +Τώρα, αν θέλετε, μπορείτε να δείτε τον κώδικα σας στο PythonAnywhere δίνοντας την εντολή `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +Μπορείτε, επίσης, να μεταβείτε στη σελίδα "Files" και απο κει να περιηγηθείτε χρησιμοποιώντας τον browser του PythonAnywhere. (Από την σελίδα Console, μπορείτε να μεταβείτε στις άλλες σελίδες του PythonAnywhere από το κουμπί menu στην πάνω δεξιά γωνία. Μόλις είστε σε μία από τις σελίδες, υπάρχουν συνδέσεις με τις άλλες πάνω στην κορυφή.) + +## Τώρα είστε ζωντανά! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Σημείωση** Αυτός είναι ένας οδηγός για αρχάριους και κατά τη διάρκεια του deploying παρακάμψαμε κάποια βήματα τα οποία είναι πολύ σημαντικά από άποψη ασφάλειας. Αν και όταν θελήσετε να εμπλουτίσετε ή να φτιάξετε ένα νέο project, καλό θα ήταν να συμβουλευτείτε το [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) για μερικές συμβουλές ασφάλειας. + +## Συμβουλές debugging + +Αν λάβετε κάποιο σφάλμα καθώς τρέχετε το script `pa_autoconfigure_django.py`, δείτε τα ακόλουθα: + +- Έχετε ξεχάσει να δημιουργήσετε ένα PythonAnywhere API token. +- Έχετε κάνει λάθος στο GitHub URL +- Αν δείτε ένα σφάλμα που λέει *«Could not find your settings.py»*, είναι πιθανώς επειδή δεν συμπεριλάβατε όλα τα αρχεία σας στο repo ή/και δεν έχετε κάνει push τις αλλαγές σας στο GitHub επιτυχώς. Δείτε ξανά την ενότητα Git παραπάνω +- Αν προηγουμένως έχετε εγγραφεί για λογαριασμό PythonAnywhere και έχετε παρουσιάσει σφάλμα στο collectstatic, πιθανόν να έχετε μια παλαιότερη έκδοση του SQLite (π. χ. 3.8.2) στο λογαριασμό σας. Σε αυτή την περίπτωση, εγγραφείτε με νέο λογαριασμό και δοκιμάστε τις εντολές στην ενότητα PythonAnywhere παραπάνω. + +Αν δείτε ένα σφάλμα όταν προσπαθείτε να επισκεφθείτε την ιστοσελίδα σας, το πρώτο μέρος για debbuging είναι το αρχείο **error log**. Θα βρείτε ένα σύνδεσμο για το error log στο ["Web" page](https://www.pythonanywhere.com/web_app_setup/) του PythonAnywhere. Δείτε εάν υπάρχουν μηνύματα σφάλματος εκεί. Τα πιο πρόσφατα είναι στο κάτω μέρος. + +Υπάρχουν επίσης ορισμένες [γενικές συμβουλές εντοπισμού σφαλμάτων στο PythonAnywhere](http://help.pythonanywhere.com/pages/DebuggingImportError). + +Και θυμηθείτε, ο εκπαιδευτής σας είναι είδω να σας βοηθήσει! + +# Δείτε το site σας! + +Η αρχική σελίδα του site σας θα λέει "Δούλεψε", όπως ακριβώς εμφανίστηκε στον υπολογιστή σας. Μεταβείτε στη διαχειριστική σελίδα προσθέτοντας το `/admin/` στο τέλος του URL. Κάντε login χρησιμοποιώντας το όνομα χρήστη και τον κωδικό σας και θα δείτε την γνώριμη σελίδα που σας επιτρέπει να προσθέστε χρήστες, posts και άλλα. Θημηθείτε, ο λόγος που δεν βλέπετε τα posts σας είναι διότι η βάση δεδομένων στο PythonAnywhere είναι "κενή" από αυτή του τοπικού υπολογιστή σας. + +Μόλις δημιουργήσετε μερικά posts, πηγαίνετε πάλι στην αρχική σελίδα του site σας. Από αυτό εδώ το σημείο και ύστερα θα πρέπει να εργάζεστε πρώτα τοπικά στον υπολογιστή σας για τυχόν αλλαγές και μετά να τις ανεβάζετε στον server. Αυτό είναι μια κοινή καλή πρακτική. Όταν λέμε αλλαγές, δεν εννοούμε προσθήκη posts, users κλπ αλλά αλλαγές στον κώδικα. Αυτό επιτρέπει να εργάζεστε και να πειραματίζεστε τοπικά δίχως να χαλάσετε κάτι στο site σας που είναι στον αέρα. Πολύ καλό, εε; + +Πείτε στον εαυτό σας ένα *ΜΕΓΑΛΟ* "ΣΥΓΧΑΡΗΤΗΡΙΑ"! Το ανέβασμα σε κάποιον server αποτελεί ένα από τα δυσκολότερα βήματα του web development και συνήθως παίρνει αρκετές μέρες για να επιτευχθεί. Όμως εσείς έχετε το site σας live, στο internet! \ No newline at end of file diff --git a/el-GR/deploy/install_git.md b/el-GR/deploy/install_git.md new file mode 100644 index 00000000000..faf291c6030 --- /dev/null +++ b/el-GR/deploy/install_git.md @@ -0,0 +1,52 @@ +Το Git είναι ένα «σύστημα ελέγχου έκδοσης» και χρησιμοποιείται από πολλούς προγραμματιστές. Αυτό το εργαλείο μπορεί να παρακολουθήσει τις αλλαγές στα αρχεία με την πάροδο του χρόνου έτσι ώστε να μπορείτε να ανακαλέσετε συγκεκριμένες εκδόσεις σε μεταγενέστερο στάδιο. Είναι κάπως σαν την δυνατότητα "παρακολούθηση αλλαγών" σε προγράμματα επεξεργασίας κειμένου (όπως το Microsoft Word ή το LibreOffice Writer) αλλά πολύ πιο δυνατό. + +## Εγκαθιστώντας το Git + + + +Μπορείτε να κατεβάσετε το Git από το [git-scm.com](https://git-scm.com/). Μπορείτε να πατάτε "επόμενο" σε όλα τα στάδια εκτός από δύο: στο στάδιο που ρωτάει για τον προτιμώμενο επεξεργαστή κειμένου θα πρέπει να επιλέξετε το Nano και στο στάδιο με το όνομα "Adjusting your PATH environment", θα πρέπει να επιλέξετε το "Use Git and optional Unix tools from the Windows Command Prompt" (την τελευταία επιλογή). Εκτός από αυτό, οι προκαθορισμένες ρυθμίσεις είναι μια χαρά. Επίσης, οι επιλογές Checkout Windows-style και Commit Unix-style είναι μια χαρά. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Κατεβάστε το Git από το [git-scm.com](https://git-scm.com/) και ακολουθήστε τις οδηγίες. + +> **Σημείωση** Αν έχετε OS X 10.6, 10.7, ή 10.8, θα χρειαστεί να εγκαταστήσετε την έκδοση του git από εδώ: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/el-GR/deploy/signup_pythonanywhere.md b/el-GR/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..1cbb413340e --- /dev/null +++ b/el-GR/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +Το PythonAnywhere είναι μια υπηρεσία για την εκτέλεση Python κώδικα σε διακομιστές «στο σύννεφο» (cloud). Θα το χρησιμοποιήσουμε για τη φιλοξενία του site μας στο internet. + +Θα φιλοξενήσουμε το blog που χτίσαμε στο PythonAnywhere. Δημιουργήστε έναν "Beginner" λογαριασμό (δεν χρειάζεστε πιστωτική κάρτα). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![H σελίδα εγγραφής του PythonAnywhere δείχνει ένα κουμπί για να δημιουργήσετε έναν δωρεάν «Beginner» λογαριασμό - λογαριασμό αρχάριων](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Σημείωση** Όταν επιλέξετε όνομα χρήστη θυμηθείτε ότι τα urls του blog σας θα έχουν τη μορφή `yourusername.pythonanywhere.com`. Οπότε επιλέξτε είτε το συνηθισμένο σας όνομα χρήστη (πχ αυτό που βάλατε στο GitHub) είτε κάποιο που να ταιριάζει με τη θεματολογία του blog σας. Επίσης, σιγουρευτείτε ότι θα θυμάστε τον κωδικό πρόσβασης σας. + +## Δημιουργώντας ένα PythonAnywhere API token + +Αυτό είναι κάτι που πρέπει να κάνετε μόνο μια φορά. Μετά την εγραφή σας στο  PythonAnywhere θα μεταφερθείτε στο ταμπλό σας. Βρείτε το σύνδεσμο "Λογαριασμός" πάνω δεξιά στη σελίδα σας: + +![Σύνδεσμος λογαριασμού πάνω δεξιά στη σελίδα](../deploy/images/pythonanywhere_account.png) + +στη συνέχεια επιλέξτε την καρτέλα που ονομάζεται "API Token" και πατήστε το κουμπί που λεει "Δημιουργία νέου  API Token". + +![Η καρτέλα "API Token" στη σελίδα λογαριασμού](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/el-GR/django/README.md b/el-GR/django/README.md new file mode 100644 index 00000000000..c615f899a96 --- /dev/null +++ b/el-GR/django/README.md @@ -0,0 +1,27 @@ +# Τι είναι το Django; + +Το Django (*goh/ˈdʒæŋɡoʊ/jang-goh*) είναι ένα δωρεάν και ανοικτού κώδικα web framework γραμμένο σε Python. Ένα web framework είναι ένα σύνολο από στοιχεία που σας βοηθά να αναπτύξετε ιστοσελίδες πιο γρήγορα και εύκολα. + +Όταν κατασκευάζετε μία ιστοσελίδα, χρειάζεστε πάντα ένα παρόμοιο σύνολο στοιχείων: έναν τρόπο για να χειρίζεστε τον έλεγχο ταυτότητας χρήστη (εγγραφή, σύνδεση, αποσύνδεση), ένα πάνελ διαχείρισης για την ιστοσελίδα σας, φόρμες, έναν τρόπο για να ανεβάσετε αρχεία κλπ. + +Ευτυχώς για εσάς, άλλα άτομα πριν από αρκετό καιρό παρατήρησαν ότι οι προγραμματιστές ιστού αντιμετωπίζουν παρόμοια προβλήματα κατά τη δημιουργία ενός νέου ιστοτόπου και έτσι συνεργάστηκαν και δημιούργησαν τα frameworks (το Django είναι ένα από αυτά) που σας δίνουν έτοιμα συστατικά που μπορείτε να χρησιμοποιήσετε. + +Τα πλαίσια υπάρχουν για να μην χρειάζεται να "επανεφεύρετε τον τροχό" και να σας ελαφρύνουν από αρκετές εργασίες κατά την διάρκεια της κατασκευής μίας νέας ιστοσελίδας. + +## Γιατί χρειάζεστε ένα framework; + +Για να καταλάβουμε τι είναι πραγματικά το Django, πρέπει να ρίξουμε μία πιο προσεκτική ματιά στους διακομιστές (servers). Το πρώτο πράγμα είναι ότι ο διακομιστής θα πρέπει να ξέρει τι θέλετε να εξυπηρετήσει σε μια ιστοσελίδα. + +Φανταστείτε ένα γραμματοκιβώτιο (θύρα), το οποίο παρακολουθείται για εισερχόμενα γράμματα (αιτήματα). Αυτό γίνεται από έναν διακομιστή διαδικτύου (web server). Ο διακομιστής διαδικτύου διαβάζει το γράμμα και αποκρίνεται με μια ιστοσελίδα. Αλλά όταν θέλετε να στείλετε κάτι, πρέπει να έχει και κάποιο περιεχόμενο. Και το Django είναι κάτι που σας βοηθάει να δημιουργήσετε αυτό το περιεχόμενο. + +## Τι συμβαίνει όταν κάποιος ζητά μια ιστοσελίδα από το διακομιστή σας; + +Όταν ένα αίτημα φτάσει σε ένα διακομιστή δικτύου, περνάει στο Django το οποίο προσπαθεί να καταλάβει τι ζητάει αυτό το αίτημα στην ουσία. Λαμβάνει πρώτα μια διεύθυνση σελίδας δικτύου και προσπαθεί να καταλάβει τι να κάνει. Αυτό το κομμάτι γίνεται από τον **urlresolver** του Django (σημειώστε ότι η διεύθυνση ενός ιστότοπου ονομάζεται URL - Uniform Resource Locator - και έτσι το όνομα *urlresolver* βγάζει νόημα). Παρόλαυτα δεν είναι πολύ έξυπνο. Παίρνει μια λίστα από μοτίβα και προσπαθεί να ταιριάξει την διεύθυνση URL. Το Django ελέγχει τα μοτίβα από πάνω προς τα κάτω και αν κάτι ταιριάζει, μεταβιβάζει το αίτημα στην σχετική λειτουργία (η οποία ονομάζεται *view*). + +Φανταστείτε έναν ταχυδρόμο με ένα γράμμα. Περπατάει στην οδό και ελέγχει κάθε αριθμό σπιτιού αν είναι ίδιος με τον αντίστοιχο αριθμό στο γράμμα. Αν ταιριάζει, βάζει το γράμμα εκεί. Αυτός είναι ο τρόπος που λειτουργεί ο urlresolver! + +Στο *view*, γίνονται όλα τα ενδιαφέροντα πράγματα: μπορούμε να δούμε μια βάση δεδομένων για να ψάξουμε για μερικές πληροφορίες. Μήπως ο χρήστης ζήτησε να αλλάξει κάτι στα δεδομένα; Όπως ένα γράμμα που λέει "Παρακαλώ, αλλάξτε την περιγραφή της δουλειάς μου.» Το *view* μπορεί να ελέγξει αν επιτρέπεται να το κάνετε αυτό και στη συνέχεια ενημερώνει την περιγραφή της δουλειάς σας και στείλνει πίσω ένα μήνυμα: "Έγινε!". Έπειτα το *view* παράγει ένα response και το Django το στέλνει πίσω στον web browser του χρήστη και προβάλεται στην οθόνη. + +Φυσικά, η παραπάνω περιγραφή είναι λίγο απλοποιημένη, αλλά δεν χρειάζεται να γνωρίζετε όλα τα τεχνικά ζητήματα ακόμη. Μια γενική ιδέα είναι αρκετή. + +Έτσι αντί να αφιερώνουμε πάρα πολύ χρόνο σε λεπτομέρειες, θα ξεκινήσουμε απλά δημιουργώντας κάτι με το Django και θα μάθουμε όλα τα σημαντικά κομμάτια καθοδόν! \ No newline at end of file diff --git a/el-GR/django_admin/README.md b/el-GR/django_admin/README.md new file mode 100644 index 00000000000..587f82fca01 --- /dev/null +++ b/el-GR/django_admin/README.md @@ -0,0 +1,57 @@ +# Διαχείριση μέσω Django admin + +Για να προσθέσουμε, επεξεργαστούμε και να διαγράψουμε τις δημοσιεύσεις που έχουμε αναρτήσει, θα χρησιμοποιήσουμε την εφαρμογή Django admin. + +Ας ανοίξουμε το αρχείο `blog/admin.py` μέσα σε έναν code editor και ας αντικαταστήσουμε τα περιεχόμενα του με τα ακόλουθα: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +Με τον παραπάνω κώδικα, εισάγουμε το μοντέλο Post (δηλαδή τον πίνακα της βάσης δεδομένων με το όνομα Post) όπως ορίστηκε από το προηγούμενο κεφάλαιο. Για να κάνουμε το μοντέλο μας ορατό στην σελίδα διαχείρισης θα πρέπει να το "εγγράψουμε" (να το κάνουμε register) με την συνάρτηση `admin.site.register(Post)`. + +Εντάξει λοιπόν, ας ρίξουμε μια ματιά στο Post μοντέλο μας. Θυμηθείτε ότι πρέπει πρώτα να πληκτρολογήσουμε `python manage.py runserver` στην κονσόλα μας ώστε να ξεκινήσει ο development server. Πηγαίνετε στον browser και πληκτρολογήστε http://127.0.0.1:8000/admin/. Θα δείτε μία σελίδα σύνδεσης όπως αυτή: + +![Login page](images/login_page2.png) + +Για να συνδεθείτε, χρειάζεται να δημιουργήσετε έναν *superuser*, δηλαδή έναν χρήστη ο οποίος θα έχει δικαιώματα σε οτιδήποτε σε αυτή την σελίδα. Πηγαίνετε πίσω στην γραμμή εντολών, πατήστε Ctrl + c για να σταματήσετε τον development server Που ήδη τρέχει, πληκτρολογήστε `python manage.py createsuperuser` και πατήστε enter. + +> Θυμηθείτε, για να γράψετε νέες εντολές ενώ ο server εκτελείται, ανοίξτε μια νέα κονσόλα και ενεργοποιήστε το virtualenv. Είδαμε πως να γράφετε νέες εντολές μέσα στο κεφάλαιο **Το πρώτο σας Django project!**, στην ενότητα **Ξεκινώντας τον web server**. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +Όταν σας ζητηθεί, πληκτρολογήστε το όνομα χρήστη σας (πεζά, δίχως κενά), το email σας και ένα password. **Μην ανησυχείτε όταν πληκτρολογείτε τον κωδικό σας και δεν βλέπετε κάτι στην οθόνη. Έτσι πρέπει να είναι.** Πληκτρολογήστε τον και μετά πατήστε `enter` για να συνεχίσετε. Η απόκριση από το τερματικό θα μοιάζει κάπως έτσι (όπου "όνομα χρήστη" και "email" θα είναι τα δικά σας): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Αν ο server δεν τρέχει κάντε το τώρα: <0>python manage.py runserver. Μετά, επιστρέψτε στον browser σας. Κάντε login και εισάγετε το όνομα χρήστη και τον κωδικό σας. Θα πρέπει να δείτε, επιτέλους, την κεντρική σελίδα διαχείρισης του Django. + +![Django admin](images/django_admin3.png) + +Πηγαίνετε στα Posts και πειραματιστείτε με αυτά. Προσθέστε πέντε ή έξι posts. Μην ανησυχείτε για το περιεχόμενο των posts. Είναι μονάχα ορατό σε εσάς, στον υπολογιστή σας. Μπορείτε να κάνετε αντιγραφή-επικόλληση κείμενο από αυτόν εδώ τον οδηγό για να γλυτώσετε χρόνο. :) + +Σιγουρευτείτε ότι δύο ή τρία posts (αλλά όχι όλα) έχουν συμπληρώσει το πεδίο "publish date". Θα μας βοηθήσει αυτό αργότερα. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +Αυτή είναι μάλλον μια καλή στιγμή να πιείτε μια γουλιά καφέ (ή τσάι) ή κάτι να φάτε για να γεμίσετε ενέργεια. Μόλις δημιουργήσατε το πρώτο σας Django model. Αξίζετε ένα μικρό διάλλειμα! \ No newline at end of file diff --git a/el-GR/django_forms/README.md b/el-GR/django_forms/README.md new file mode 100644 index 00000000000..a2127c1305c --- /dev/null +++ b/el-GR/django_forms/README.md @@ -0,0 +1,479 @@ +# Φόρμες Django + +Το τελευταίο που έμεινε για την ιστοσελίδα μας είναι να δημιουργήσουμε μια όμορφη φόρμα για την εισαγαγωγή και τροποποίηση των post μας. Θα μπορούσαμε να χρησιμοποιήσουμε το Django `admin` αλλά είναι αρκετά πολύπλοκο να τροποποιήσουμε και να κάνουμε όμορφη τη φόρμα εισαγωγής εκεί. Με τις `φόρμες` έχουμε τον πλήρη έλεγχο στο περιβάλλον του χρήστη. Μπορούμε να κάνουμε ότι μπορούμε να φανταστούμε! + +Μία από τις ευκολίες των Django φορμών είναι ότι μπορούμε να ξεκινήσουμε από το μήδεν ή να χρησιμοποιήσουμε το `ModelForm` που ουσιαστικά αποθηκεύει τα δεδομένα της φόρμας στο μοντέλο (ή διαφορετικά στο σωστό πίνακα της βάσης μας). + +Αυτό είναι ακριβώς που θέλουμε να κάνουμε: δηλαδή να δημιουργήσουμε εύκολα μια φόρμα εισαγωγής δεδομένων για το ήδη υπάρχων `Post` μοντέλο. + +Οπώς κάθε άλλο σημαντικό τμήμα του Django, οι φόρμες εισαγωγής "ζούν" στο δικό τους αρχείο: `forms.py`. + +Πρέπει να δημιουργήσουμε το αρχείο forms.py μέσα στο φάκελο `blog`. + + blog + └── forms.py + + +Ωραία. Ας ανοίξουμε τον επεξεργαστή κώδικα και ας γράψουμε τον ακόλουθο κώδικα: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Θα χρειαστεί να κάνουμε import τις Django forms πρώτα (`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` θα παράγεται αυτόματα όταν δημιουργούμε ένα post (πχ μέσω κώδικα), σωστά; + +Αυτό ήταν! Αυτό που μας απομένει είναι να χρησιμοποιήσουμε την φόρμα μας μέσα σε ένα *view* ώστε να είναι διαθεσίμη μέσω ενός template. + +Οπότε, για ακόμα μια φορά, θα χρειαστεί να συνδέσουμε τη σελίδα με ένα url, ένα view και ένα template. + +## Πως συνδέουμε μια σελίδα με την φόρμα μας + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* Πρέπει να εμφανίσουμε τη φόρμα. Μπορούμε να το κάνουμε αυτό (για παράδειγμα) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* Χρειαζόμαστε ένα κουμπί `Αποθήκευση`. Το κάνουμε αυτό με ένα κουμπί HTML: ``. +* Και στο τέλος, ακριβώς μετά το tag `
` πρέπει να προσθέσουμε {% raw %}`{% csrf_token %}`{% endraw %}. Αυτό είναι πολύ σημαντικό, αφού καθιστά τις φόρμες σας ασφαλείς! Εάν ξεχάσετε αυτό το κομμάτι, το Django θα παραπονεθεί όταν προσπαθήσετε να αποθηκεύσετε τη φόρμα: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Αποθηκεύοντας τη φόρμα + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Επεξεργασία φόρμας + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Ασφάλεια + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## Ένα πράγμα ακόμα: ώρα να το ανεβάσετε! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* Πρώτα κάντε commit τον νέο σας κώδικα και έπειτα push στο GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Έπειτα, στην [κονσόλα Bash του PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Τέλος, επισκεφτείτε τη σελίδα σας ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (χρησιμοποιήστε το κουμπί του menu στην πάνω δεξιά γωνία της κονσόλας) και κλικάρετε **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/el-GR/django_installation/README.md b/el-GR/django_installation/README.md new file mode 100644 index 00000000000..43e94971103 --- /dev/null +++ b/el-GR/django_installation/README.md @@ -0,0 +1,7 @@ +# Εγκατάσταση του Django + +> **Σημείωση** Αν χρησιμοποιείτε ένα Chromebook, παραλείψτε αυτό το κεφάλαιο και σιγουρευτείτε ότι ακουλουθείτε τις [Chromebook Setup](../chromebook_setup/README.md) οδηγίες. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/el-GR/django_installation/instructions.md b/el-GR/django_installation/instructions.md new file mode 100644 index 00000000000..9b8893494fe --- /dev/null +++ b/el-GR/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Μέρος αυτής της ενότητας βασίζεται στους οδηγούς των 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. + +## Εικονικό περιβάλλον + +Πριν την εγκατάσταση του Django, θα εγκαταστήσουμε ενα εξαιρετικά χρήσιμο εργαλείο για να κρατήσουμε το περιβάλλον του υπολογιστή σας τακτοποιημένο και καθαρό. Μπορείτε να παραβλέψετε αυτό το βήμα, αλλά προτείνουμε να το ακολουθήσετε καθώς αν δεν το ακολουθήσετε υπάρχει σοβαρή πιθανότητα να προκύψουν σφάλματα αργότερα. Ξεκινώντας με την καλύτερη δυνατή εγκατάσταση, θα αποφύγετε πολλά προβλήματα στο μέλλον! + +Ας δημιουργήσουμε λοιπόν ενα **εικονικό περιβάλλον** (το αποκαλούμενο *virtualenv*). Το virtualenv θα απομονώσει την κάθε εγκατάσταση Python/Django ανά έργο (project). Αυτό σημαίνει ότι οι αλλαγές που κάνετε σε μια ιστοσελίδα (έργο - project) δεν θα επηρεάζουν οποιεσδήποτε άλλες ιστοσελίδες που αναπτύσσετε παράλληλα. Κάθε ιστοσελίδα θα έχει τα δικά της πακέτα και κάθε πακέτο την δική του έκδοση (version). Καλό, ε; + +Το μόνο που χρειάζεται να κάνετε είναι να βρείτε έναν φάκελο στον οποίο θέλετε να δημιουργήσετε το `virtualenv`. Για παράδειγμα, το home directory σας. Στα Windows, θα μοιάζει κάπως έτσι `C:\Users\Name` ( όπου `Name` είναι το όνομα της σύνδεσης σας). + +> **ΣΗΜΕΙΩΣΗ:** Στα Windows, σιγουρευτείτε ότι αυτός ο κατάλογος δεν περιέχει χαρακτήρες που τονίζονται ή ειδικούς χαρακτήρες. Αν το όνομα χρήστη σας περιέχει χαρακτήρες που τονίζονται, χρησιμοποιείστε ένα διαφορετικό φάκελο, για παράδειγμα `C:\djangogirls`. + +Για αυτό το tutorial θα χρησιμοποιήσουμε ένα νεο φάκελο `djangogirls` από το home directory σας: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +Θα δημιουργήσουμε ένα virtualenv με το όνομα `myvenv`. Η γενική εντολή είναι: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +Για την δημιουργία ενός νέου `virtualenv`, θα χρειαστεί να ανοίξετε την γραμμή εντολών στον υπολογιστή σας (κονσόλα) και να τρέξετε την εντολή `python -m venv myvenv`. Θα μοιάζει κάπως έτσι: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Όπου `myvenv` είναι το όνομα του `virtualenv` σας. Μπορείτε να χρησιμοποιήσετε οποιοδήποτε άλλο όνομα, αλλά πρέπει να είναι αγγλικοί χαρακτήρες, πεζά, χωρίς κενά, εμφάσεις ή άλλους ειδικούς χαρακτήρες. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +Μπορούμε να δημιουργήσουμε ένα `virtualenv` σε Linux και σε OS X τρέχοντας την εντολή `python3 -m venv myvenv`. Θα μοιάζει κάπως έτσι: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +Το `myvenv` είναι το όνομα του `virtualenv` σας. Μπορείτε να χρησιμοποιήσετε οποιοδήποτε άλλο όνομα, αλλα πρέπει να είναι αγγλικοί χαρακτήρες, πεζά, χωρίς κενά και χωρίς άλλους ειδικούς χαρακτήρες. Είναι επίσης καλή ιδέα να κρατήσετε το όνομα μικρό - θα το αναφέρετε συχνά! + +> **ΣΗΜΕΙΩΣΗ:** Σε μερικές εκδόσεις των Debian/Ubuntu ίσως εμφανιστεί το ακόλουθο σφάλμα: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. Στα λειτουργικά συστήματα Debian/Ubuntu, θα χρειαστεί να εγκαταστήσετε το πακέτο python3-venv χρησιμοποιώντας την ακόλουθη εντολή. +> apt install python3-venv +> Ίσως χρειαστεί να χρηιμοποιήσετε sudo με αυτή την εντολή. Αφού εγκατασταθεί επιτυχώς το πακέτο python3-venv, επαναδημιουργήστε το εικονικό σας περιβάλλον. +> +> +> Σε αυτή την περίπτωση, ακολουθήστε τις οδηγίες παραπάνω και εγκαταστήστε το πακέτο `python3-venv`: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **ΣΗΜΕΙΩΣΗ:** Σε μερικές εκδόσεις των Debian/Ubuntu η ενεργοποίηση του virtual environment με αυτόν τον τρόπο, παράγει το ακόλουθο σφάλμα: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Για την επίλυση του χρησιμοποιήστε την εντολή `virtualenv`. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **ΣΗΜΕΙΩΣΗ:** Αν λάβετε κάποιο σφάλμα όπως +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> τότε τρέξτε: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Δουλεύοντας με το virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Ξεκινήστε το εικονικό σας περιβάλλον εκτελώντας: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. Σε αυτή την περίπτωση, ανοίξτε ένα άλλο Windows PowerShell με την επιλογή "Εκτέλεση ως διαχειριστής". Έπειτα δοκιμάστε να πληκτρολογήσετε την ακόλουθη εντολή πριν ξεκινήσετε το εικονικό σας περιβάλλον: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Εγκατάσταση πακέτων με τα requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/el-GR/django_models/README.md b/el-GR/django_models/README.md new file mode 100644 index 00000000000..dca03e1d57a --- /dev/null +++ b/el-GR/django_models/README.md @@ -0,0 +1,201 @@ +# Django μοντέλα (models) + +Αυτό που θέλουμε να δημιουργήσουμε τώρα είναι κάτι που θα αποθηκεύει όλες τις αναρτήσεις του blog μας. Αλλά για να είμαστε σε θέση να το κάνουμε, πρέπει να μιλήσουμε λίγο για το τι ονομάζουμε `"αντικείμενα" (objects)`. + +## Objects + +Υπάρχει μια έννοια στον προγραμματισμό που ονομάζεται `"Αντικειμενοστραφής προγραμματισμός`. Η ιδέα είναι ότι αντί να γράφετε τα πάντα ως μια βαρετή ακολουθία από προγραμματιστικές εντολές, μπορούμε να μοντελοποιήσουμε τα πράγματα και να καθορίσουμε πως αλληλεπιδρούν μεταξύ τους. + +Άρα, τι είναι ένα αντικείμενο; Είναι μια συλλογή από ιδιότητες και συμπεριφορές. Ακούγεται παράξενο, αλλά θα σας δώσουμε ένα παράδειγμα. + +Εάν θέλουμε να μοντελοποιήσουμε μια γάτα, θα δημιουργήσουμε ένα αντικείμενο `Γάτα` το οποίο έχει κάποιες ιδιότητες όπως `χρώμα`, `ηλικία`, `διάθεση` (όπως καλή, κακή, νυσταγμένη :)), και `ιδιοκτήτης`(που θα μπορεί να ανατεθεί σε ένα αντικείμενο `άτομο` ή ίσως, στην περίπτωση μιας αδέσποτης γάτας, αυτή η ιδιότητα θα μπορούσε να είναι άδεια). + +Έπειτα η `γάτα` έχει κάποιες δράσεις `γουργούρισμα`, `ξύσιμο` ή `τάισμα`( σε αυτή την περίπτωση, θα δώσουμε στην γάτα λίγη `γατοτροφή`, που θα μπορούσε να είναι ένα ξεχωριστό αντικείμενο με ιδιότητες, όπως `γεύση`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +Βασικά η ιδέα είναι να περιγράψουμε τα αληθινά πράγματα στον κώδικα με ιδιότητες (που ονομάζονται `object properties`) και συμπεριφορές (που ονομάζονται `methods`). + +Πώς θα μοντελοποιήσουμε τότε τις αναρτήσεις του blog; Θέλουμε να κατασκευάσουμε ένα blog, σωστά; + +Πρέπει να δώσουμε απάντηση στο ερώτημα: τι είναι μία ανάρτηση στο blog; Τι ιδιότητες πρέπει να έχει; + +Λοιπόν, σίγουρα μία ανάρτηση στο blog μας χρειάζεται κάποιο κείμενο με το περιεχόμενό του και έναν τίτλο, σωστά; Θα ήταν επίσης ωραίο να ξέρουμε ποιος το έγραψε αυτό. Έτσι χρειαζόμαστε έναν συγγραφέα. Τέλος, θέλουμε να γνωρίζουμε πότε δημιουργήθηκε και δημοσιεύτηκε η συγκεκριμένη ανάρτηση. + + Post + -------- + title + text + author + created_date + published_date + + +Τι είδους πράγματα θα μπορούσαν να γίνουν με μια ανάρτηση στο blog; Θα ήταν ωραίο να έχουμε κάποια `method` που δημοσιεύει την ανάρτηση, σωστά; + +Έτσι, θα χρειαστούμε μια μέθοδο `publish`. + +Δεδομένου ότι γνωρίζουμε ήδη τι θέλουμε να επιτύχουμε, ας ξεκινήσουμε τη μοντελοποίηση στο Django! + +## Django model + +Γνωρίζοντας τι είναι ένα αντικείμενο, μπορούμε να δημιουργήσουμε ένα μοντέλο Django για την ανάρτηση στο blog μας. + +Ένα μοντέλο στο Django είναι ένα ιδιαίτερο είδος αντικειμένου το οποίο αποθηκεύεται στη βάση δεδομένων `database`. Η βάση δεδομένων είναι μια συλλογή δεδομένων. Είναι εκεί όπου θα αποθηκευτούν όλες οι πληροφορίες για τους χρήστες, τις αναρτήσεις στο blog, κλπ. Θα χρησιμοποιήσουμε την βάση δεδομένων SQLite για την αποθήκευση των δεδομένων μας. Αυτός είναι η προεπιλεγμένη βάση δεδομένων του Django. Είναι αρκετό για εμάς για την ώρα. + +Μπορείτε να σκεφτείτε ένα μοντέλο της βάσης δεδομένων ως ένα υπολογιστικό φύλλο με στήλες (πεδία) και γραμμές (δεδομένα). + +### Δημιουργία μιας εφαρμογής + +Για να κρατήσουμε τα πάντα τακτοποιημένα, θα δημιουργήσουμε μια ξεχωριστή εφαρμογή μέσα στο project μας. Είναι πολύ ωραίο να έχουμε τα πάντα οργανωμένα από την αρχή. Για την δημιουργία μιας εφαρμογής θα χρειαστεί να τρέξουμε την ακόλουθη εντολή στην κονσόλα (από τον φάκελο `djangogirls` όπου βρίσκεται το αρχείο `manage.py`): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +Θα παρατηρήσετε ότι ένας νέος φάκελος με το όνομα `blog` δημιουργήθηκε και περιέχει έναν αριθμό αρχείων. Οι φάκελοι και τα αρχεία στο project μας πρέπει να μοιάζουν κάπως έτσι: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +Μετά την δημιουργία μίας εφαρμογής, πρέπει επίσης να πούμε στο Django ότι πρέπει να τη χρησιμοποιήσει. Το κάνουμε αυτό μέσα στο αρχείο `mysite/settings.py`. Ανοίξτε το. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. Έτσι το τελικό προϊόν πρέπει να μοιάζει κάπως έτσι: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Δημιουργία ενός post model + +Μέσα στο αρχείο `blog/models.py` ορίζουμε όλα τα objects με το όνομα `Models`. Αυτό είναι ένα μέρος όπου θα ορίσουμε το post μοντέλο μας. + +Ας ανοίξουμε το αρχείο `blog/models.py`, διαγράψτε τα περιεχόμενα του και γράψτε τα εξής: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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` είναι γραμμές που εισάγουν λειτουργίες από άλλα Python αρχεία (αυτά με την κατάληξη .py). Έτσι αντί να κάνουμε αντιγραφή-επικόλληση κώδικα, πολύ απλά συμπεριλαμβάνουμε κώδικα από άλλα αρχεία με τη χρήση του `from ... import ...`. + +`class Post(models.Model):` – αυτή η γραμμή ορίζει το μοντέλο μας (είναι μια κλάση που με τη σειρά της είναι και αυτή ένα `object`). + +- Η λέξη `class` είναι μια ιδιαίτερη λέξη-κλειδί που καθορίζει τον ορισμό μιας κλάσης. +- Η λέξη `Post` είναι το όνομα του μοντέλου μας. Μπορούμε να του δώσουμε όποιο όνομα θέλουμε (αλλά πρέπει να αποφεύγουμε ιδιαίτερους χαρακτήρες και κενά). Πάντα το όνομα μιας κλάσης να ξεκινάει με ένα κεφαλαίο γράμμα. +- Η γραμμή `models.Model` σημαίνει ότι το Post είναι ένα Django Model. Με αυτό τον τρόπο το Django θα ξέρει ότι θα πρέπει να αποθηκεύεται σε μια βάση δεδομένων. + +Τώρα ορίζουμε τα properties που λέγαμε: `title`, `text`, `created_date`, `published_date` και `author`. Για να το κάνουμε αυτό θα πρέπει να ορίσουμε τον τύπο τιμών που θα δέχεται το κάθε πεδίο (είναι κείμενο; αριθμός; ημερομηνία; κάποια συσχέτιση με ένα άλλο object, όπως ένας χρήστης;) + +- `models.CharField` – έτσι δηλώνετε ότι θέλετε να ορίσετε ένα κείμενο με συγκεκριμένο αριθμό χαρακτήρων. +- `models.TextField`- αυτό είναι για μεγάλα κείμενα χωρίς όριο. Ακούγεται ιδανικό για περιεχόμενο δημοσιεύσεων blog, έτσι δεν είναι; +- `models.DateTimeField`- αυτό είναι για ημερομηνία και ώρα. +- `models.ForeignKey`- αυτό είναι ένας σύνδεσμος για ένα άλλο μοντέλο. + +Δεν θα εξηγήσουμε κάθε κομμάτι του κώδικα διότι θα πάρει αρκετό χρόνο. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +Τι γίνεται με την μέθοδο `def publish(self):`; Αυτή είναι ακριβώς η μέθοδος `publish` για την οποία μιλούσαμε πριν. `def` σημαίνει ορίζουμε μια συνάρτηση/μέθοδο (ανάλογα αν είναι μέρος τηε κλάσης ή όχι) και `publish` είναι το όνομα της. Μπορείτε να αλλάξετε το όνομα της μεθόδου αν θέλετε. Ο κανόνας ονομασίας είναι ότι χρησιμοποιούμε πεζά γράμματα και κάτω παύλες αντί για κενά. Αν χρησιμοποιήσετε κενά τότε λάβετε σφάλμα. Για παράδειγμα, μια μέθοδος που υπολογίζει την μέση τιμή θα λεγόταν `calculate_average_price`. + +Οι μέθοδοι συχνά κάνουν `return` κάτι, δηλαδή επιστρέφουν μια τιμή ή οτιδήποτε άλλο. Μπορεί όμως και όχι. Υπάρχει ένα παράδειγμα αυτού στη μέθοδο `__str__`. Σε αυτό το σενάριο, όταν καλούμε την `__str__()` θα λάβουμε ένα κείμενο (**string**) με τον τίτλο του post. + +Επίσης προσέξτε ότι και το `def publish(self):` και το `def __str__(self):` είναι δηλωμένα μέσα στην κλάση μας (με κενά ή με tab). Επειδή η Python είναι ευαίσθητη στα κενά (στους κενούς χαρακτήρες), θα πρέπει να "βάλουμε" τις μεθόδους μας μέσα στην κλάση. Αλλιώς, οι μέθοδοι δεν θα ανήκουν στην κλάση και μπορεί να συναντήσετε απρόοπτη συμπεριφορά. + +Εάν κάτι ακόμα δεν είναι ξεκάθαρο σχετικά με τα μοντέλα, μη διστάσετε να ρωτήσετε τον επιτηρητή σας! Ξέρουμε ότι είναι περίπλοκο, ειδικά όταν μαθαίνετε τι είναι τα αντικείμενα και συναρτήσεις ταυτόχρονα. Αλλά ελπίζουμε να μοιάζει λιγότερο μαγικό για εσάς τώρα! + +### Δημιουργία πινάκων για μοντέλα στην βάση δεδομένων σας + +Το τελευταίο βήμα εδώ είναι να προσθέσουμε το νέο μοντέλο μας στην βάση δεδομένων μας. Πρώτα πρέπει να ενημερώσουμε το Django ότι έχουμε κάποιες αλλαγές στο μοντέλο μας. (Μόλις το δημιουργήσαμε!) Πηγαίνετε στο παράθυρο της κονσόλας σας και πληκτρολογήστε `python manage.py makemigrations blog`. Θα μοιάζει κάπως έτσι: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Σημείωση:** Θυμηθείτε να αποθηκεύετε τα αρχεία που επεξεργάζεστε. Αλλιώς, ο υπολογιστής σας θα εκτελέσει τις προηγούμενες εκδόσεις που μπορεί να σας δώσει μηνύματα απρόοπτων σφαλμάτων. + +Το Django προετοίμασε ένα αρχείο migration για εμάς που πρέπει τώρα να εφαρμόσουμε στην βάση δεδομένων μας. Πληκτρολογήστε `python manage.py migrate blog` και τo αποτελέσματα πρέπει να είναι όπως παρακάτω: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Ζήτω! Το Post μοντέλο μας είναι στην βάση δεδομένων! Θα ήταν ωραίο να το δούμε, σωστά; Πηγαίνετε στο επόμενο κεφάλαιο για να δείτε πως μοιάζει η ανάρτηση σας! \ No newline at end of file diff --git a/el-GR/django_orm/README.md b/el-GR/django_orm/README.md new file mode 100644 index 00000000000..170d5109fa0 --- /dev/null +++ b/el-GR/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM και QuerySets + +Σε αυτό το κεφάλαιο θα μάθετε πως το Django συνδέεται στην βάση δεδομένων και αποθηκεύει δεδομένα μέσα της. Ας ξεκινήσουμε! + +## Τι είναι ένα QuerySet; + +Ένα QuerySet είναι, στην ουσία, μία λίστα αντικειμένων ενός Μοντέλου. Τα QuerySets σας επιτρέπουν να διαβάσετε τα δεδομένα από την βάση δεδομένων, να τα φιλτράρετε και να τα ταξινομήσετε. + +Είναι πιο εύκολο να μάθεις κάνοντας το. Πάμε να δοκιμάσουμε; + +## Παράθυρο εντολών Django (django shell) + +Άνοιξτε την κονσόλα (όχι στο PythonAnywhere) και πληκτρολογήστε αυτήν την εντολή: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +Το αποτέλεσμα πρέπει να είναι σαν αυτό: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +Είστε τώρα στην διαδραστική κονσόλα του Django. Είναι ακριβώς όπως το παράθυρο εντολών της Python, αλλά με μια μικρή επιπρόσθετη μαγεία του Django. :) Φυσικά, μπορείτε να χρησιμοποιήσετε όλες τις εντολές Python εδώ. + +### Όλα τα αντικείμενα + +Ας προσπαθήσουμε να εμφανίσουμε όλες τις δημοσιεύσεις του blog μας πρώτα. Μπορείτε να το κάνετε με την ακόλουθη εντολή: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Ωχ! Εμφανίστηκε ένα λάθος, μας λέει ότι δεν υπάρχει καμία δημοσίευση. Είναι σωστό. Ξεχάσαμε να το εισάγουμε πρώτα (να το κάνουμε, δηλαδή, import)! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +Εισάγουμε το μοντέλο `Post` από το module `blog.models`. Ας προσπαθήσουμε να εμφανίσουμε όλες τις αναρτήσεις ξανά: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +Αυτή είναι μια λίστα των αναρτήσεων που δημιουργήσαμε νωρίτερα! Δημιουργήσαμε αυτές τις αναρτήσεις χρησιμοποιώντας το περιβάλλον διαχειριστή Django. Αλλά τώρα θέλουμε να δημιουργήσουμε νέες αναρτήσεις χρησιμοποιώντας την Python, οπότε πως το κάνουμε αυτό; + +### Δημιουργία αντικειμένου + +Έτσι δημιουργείται ένα νέο αντικείμενο Post στην βάση δεδομένων: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Αλλά μας λείπει ένα συστατικό εδώ: `εγώ`. Χρειαζόμαστε να περάσουμε μία παρουσία του μοντέλου `User` ως τον author. Πως το κάνουμε αυτό; + +Ας εισάγουμε το μοντέλο User πρώτα: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +Τι χρήστες έχουμε στην βάση δεδομένων μας; Δοκιμάστε αυτό: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +Αυτός είναι ο χρήστης superuser που δημιουργήσαμε νωρίτερα! Ας πάρουμε ένα instance από την κλάση User τώρα (αντικαταστείστε το όνομα με το όνομα χρήστη που βάλατε νωρίτερα ως superuser): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +Όπως βλέπετε, κάνουμε ένa `get` για έναν `User` με ένα `username` το οποίο ισούται με 'ola'. Καλό! + +Τώρα μπορούμε, επιτέλους να δημιουργήσουμε το post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Ζήτω! Θέλετε να ελέγξετε αν λειτούργησε; + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +Αυτό είναι, άλλη ένα post στη λίστα! + +### Προσθέστε περισσότερα posts + +Τώρα μπορείτε να διασκεδάσετε λίγο και να προσθέσετε περισσότερες δημοσιεύσεις για να δείτε πως δουλεύει. Προσθέστε δυο-τρεις ακόμα και μετά προχωρήστε στο επόμενο μέρος. + +### Φιλτράρισμα αντικειμένων + +Ένα μεγάλο μέρος των χαρακτηριστικών των QuerySets είναι η δυνατότητα να τα φιλτράρουμε. Ας υποθέσουμε ότι θέλουμε να βρούμε όλα τα posts όπου ο χρήστης ola έγραψε. Θα χρησιμοποιήσουμε την μέθοδο `filter` αντί της `all` στην εντολή `Post.objects.all()`. Μέσα στις παρενθέσεις της μεθόδου filter δηλώνουμε τα κριτήρια αναζήτησης για αυτό που ψάχνουμε. Στην περίπτβση μας, το κριτήριο είναι ένα `author` και θέλουμε να είναι ίσο με `me`. Ο τρόπος που το γράφουμε στο Django είναι `author=me`. Τώρα ο κώδικας μοιάζει κάπως έτσι: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Ή ίσως θα θέλαμε να δούμε όλα τα posts τα οποία περιέχουν τη λέξη 'title' μέσα στο πεδίο `title`; + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Σημείωση** Υπάρχουν δύο κάτω παύλες (`_`) μεταξύ του `title` και του `contains`. Το Django ORM χρησιμοποιεί αυτόν τον κανόνα για να διαχωρίσει τα ονόματα των πεδίων των μοντέλων ("title") με τους διαχωριστές ή τα φίλτρα ("contains"). Αν χρησιμποιούσατε μόνο μια κάτω παύλα θα λαμβάνατε το σφάλμα "FieldError: Cannot resolve keyword title_contains". + +Μπορείτε επίσης να πάρετε μια λίστα από δημοσιευμένα posts. Το κάνουμε αυτό φιλτράροντας όλα τα posts που έχουν παρελθοντική ημ/νια `published_date`: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Δυστυχώς, το post που αναρτήσαμε από την Python κονσόλα δεν είναι δημοσιευμένο ακόμα. Αλλά μπορούμε να το αλλάξουμε αυτό. Πρώτα, πάρτε ένα instance από το post που θέλετε να δημοσιεύσετε: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +Και έπειτα δημοσιεύστε το με την μέθοδο `publish`: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Τώρα προσπαθήστε να πάρετε μια λίστα από δημοσιευμένα posts ξανά (πιέστε το πάνω βελάκι στο πληκτρολόγιο 3 φορές και έπειτα `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ταξινόμηση objects + +Τα QuerySets επίσης σου επιτρέπουν να ταξινομήσεις την λίστα των αντικειμένων. Ας προσπαθήσουμε να τα ταξινομήσουμε ως προς πεδίο `created_date`: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +Μπορούμε επίσης να αντιστρέψουμε την ταξινόμηση προσθέτοντας `-` στην αρχή: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +Αυτό είναι πολύ ισχυρό και σας επιτρέπει να γράψετε αρκετά σύνθετα ερωτήματα. + +Ωραία! Τώρα είστε έτοιμοι για το επόμενο μέρος! Για να κλείσετε το κέλυφος, πληκτρολογήστε αυτό: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/el-GR/django_start_project/README.md b/el-GR/django_start_project/README.md new file mode 100644 index 00000000000..e36331e55a9 --- /dev/null +++ b/el-GR/django_start_project/README.md @@ -0,0 +1,260 @@ +# Το πρώτο σας Django project! + +> Μέρος αυτού του κεφαλαίου είναι βασισμένο στους οδηγούς από την κοινότητα 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 ανήκουν στον Markus Zapke-Gründemann. + +Πρόκειται να δημιουργήσουμε ένα μικρό blog! + +Το πρώτο βήμα είναι να ξεκινήσουμε ένα νέο Django project. Βασικά αυτό σημαίνει ότι θα εκτελέσουμε μερικά scripts (εντολές) που παρέχονται από το Django τα οποία θα δημιουργήσουν τον σκελετό ενός Django project για εμάς. Αυτά είναι ένα σύμπλεγμα φακέλων και αρχείων που θα χρησιμοποιήσουμε αργότερα. + +Τα ονόματα μερικών αρχείων και φακέλων είναι πολύ σημαντικά για το Django. Δεν πρέπει να μετονομάσετε τα αρχεία που πρόκειται να δημιουργήσουμε. Μετακινώντας τα σε ένα διαφορετικό μέρος δεν είναι επίσης καλή ιδέα. Το Django χρειάζεται να διατηρήσει μία συγκεκριμένη δομή για να μπορεί να βρει σημαντικά πράγματα. + +> Θυμηθείτε να εκτελείτε τα πάντα μέσα σε κάποιο εικονικό περιβάλλον. Εάν δεν δείτε ένα πρόθεμα `(myenv)` στην κονσόλα σας, θα πρέπει να ενεργοποιήσετε το εικονικό περιβάλλον σας. Εξηγήσαμε πως να το κάνετε αυτό στο κεφάλαιο **Εγκατάσταση Django** στην ενότητα **Δουλεύοντας με το εικονικό περιβάλλον**. Σε Windows δοκιμάστε να γράψετε `myvenv\Scripts\activate` ή αν έχετε Lixux/OS X γράψτε `source myvenv/bin/activate`. + + + +Στην κονσόλα σας Mac OS X ή Linux, πρέπει να εκτελέσετε την ακόλουθη εντολή. ** Μην ξεχάσετε να προσθέσετε την τελεία `. ` στο τέλος!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> Η τελεία `.` είναι ζωτικής σημασίας επειδή λέει στην εντολή να εγκαταστήσει το Django στο τρέχον φάκελο σας ( για το οποίο η τελεία `.` είναι μία συντόμευση). +> +> **Σημείωση** Όταν πληκτρολογείτε την παραπάνω εντολή, θυμηθείτε ότι πληκτρολογείτε το κομμάτι που ξεκινά με `django-admin`. Το κομμάτι κονσόλας που εμφανίζεται εδώ `(myvenv) ~/djangogirls$` είναι απλώς ένα παράδειγμα. + + + + + +Στα Windows πρέπει να εκτελέσετε την ακόλουθη εντολή. **(Μην ξεχάσετε να προσθέσετε την τελεία `.` στο τέλος)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> Η τελεία `.` είναι ζωτικής σημασίας επειδή λέει στην εντολή να εγκαταστήσει το Django στο τρέχον φάκελο σας ( για το οποίο η τελεία `.` είναι μία συντόμευση). +> +> **Σημείωση** Όταν πληκτρολογείτε την παραπάνω εντολή, θυμηθείτε ότι πληκτρολογείτε το κομμάτι που ξεκινά με `django-admin.exe`. Το κομμάτι κονσόλας που εμφανίζεται εδώ `(myvenv) ~/djangogirls$` είναι απλώς ένα παράδειγμα. + + + +Η εντολή `django-admin.py` μπορεί να δημιουργήσει τους φακέλους και τα αρχεία για εσάς. Θα πρέπει τώρα να έχετε μια δομή φακέλων που μοιάζει κάπως έτσι: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Σημείωση**: Στην δομή φακέλων σας, θα δείτε επίσης τον `venv` φάκελο σας που δημιουργήσαμε προηγουμένως. + +Το `manage.py` είναι ένα script που βοηθά με την διαχείριση του project σας. Με αυτό θα μπορούμε να (μεταξύ άλλων πραγμάτων) ξεκινήσουμε έναν server στον υπολογιστή μας χωρίς να εγκαταστήσουμε οτιδήποτε άλλο. + +Το αρχείο `settings.py` περιέχει τις διάφορες παραμέτρους του project σας. + +Θυμάστε όταν μιλήσαμε σχετικά με ένα μεταφορέα αλληλογραφίας που ελέγχει που να παραδώσει ένα γράμμα; Το αρχείο `urls.py` περιέχει μία λίστα από σχέδια που χρησιμοποιούνται από τον `urlresolver`. + +Ας αφνοήσουμε τα υπόλοιπα αρχεία προς το παρόν καθώς δεν θα τα αλλάξουμε καθόλου. Το μόνο πράγμα που πρέπει να θυμάστε είναι να μην τα διαγράψετε κατά λάθος! + +## Αλλάζοντας τις ρυθμίσεις + +Ας κάνουμε μερικές αλλαγές στο αρχείο `mysite/settings.py`. Ανοίξτε το. + +**Σημείωση**: Κρατήστε στο μυαλό σας ότι το αρχείο `settings.py` είναι ένα κοινό Python αρχείο όπως όλα τα άλλα Python αρχεία (έχουν, δηλαδή, την κατάληξη .py). Μπορείτε να το ανοίξετε μέσα από τον επεξεργαστή κώδικα που χρησιμοποιείτε, κλικάροντας στο "File -> Open". Αυτό θα εμφανίσει ένα παράθυρο εξερεύνησης αρχείων μέσα από το οποίο επιλέγετε το αρχείο `settings.py` και το ανοίγετε. Εναλλακτικά, μπορείτε να μεταβείτε μέσα από τον φάκελο djangogirls και με δεξί κλικ να το ανοίξετε. Έπειτα, επιλέξτε τον επεξεργαστή κώδικα από την προτινώμενη λίστα προγραμμάτων. Η επιλογή του επεξεργαστή κώδικα είναι σημαντική καθώς μπορεί να έχετε άλλα προγράμματα εγκατεστημένα. + +Θα ήτνα καλό να έχουμε τη σωστή ώρα στην ιστοσελίδα μας. Πηγαίνετε στο [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) και αντιγράψτε την ζώνη ώρας σας (TZ) (πχ `Europe/Athens`). + +Στο αρχείο `settings.py`, βρείτε τη γραμμή που λέει `TIME_ZONE` και αλλάξτε την τιμή της σε αυτή που αντιγράψατε. Για παράδειγμα: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +Ο κωδικό γλώσσας (language code) αποτελείται από την γλώσσα, πχ `en` για Αγγλικά ή `el` για Ελληνικά και τον κωδικό χώρας πχ `gr` για Ελλάδα ή `ch` για την Ελβετία. Αν τα Ελληνικά είναι η μητρική σας γλώσσα, μπορείτε να προσθέσετε το παρακάτω για να αλλάξετε την γλώσσα σε Ελληνικά: Μπορείτε, δηλαδή, να έχετε ένα κουμπί "Άκυρο" μεταφρασμένο στην γλώσσα σας. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +Αν θέλετε κάποια διαφορετική γλώσσα, αλλάξτε το string LANGUAGE_CODE όπως παρακάτω με την τική που εσείς επιθυμείτε: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'el-GR' +``` + +Χρειάζεται επίσης να ρυθμίσουμε τα στατικά αρχεία μας. (Θα βρείτε τα πάντα για τα στατικά αρχεία και το CSS αργότερα στον οδηγό.) Πηγαίνετε προς τα κάτω μέχρι το *τέλος* του αρχείου και ακριβώς κάτω από την καταχώρηση `STATIC_URL`, προσθέστε μια νέα που ονομάζεται `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +Όταν το flag `DEBUG` είναι `True` και η λίστα `ALLOWED_HOSTS` είναι κενή, ο host επικυρώνεται μέσα από την ακόλουθη λίστα `[«localhost', '127.0.0.1', ' [:: 1]']`. Αυτό δεν θα ταιριάξει το hostname μας στο PythonAnywhere μόλις κάνουμε deploy την εφαρμογή μας. Οπότε θα χρειαστεί να κάνουμε την ακόλουθη αλλαγή: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Σημείωση**: Αν χρησιμοποιείτε ένα Chromebook, προσθέστε αυτή τη γραμμή στο τέλος του αρχείου settings.py: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Επίσης προσθέστε `".amazonaws.com"` στη λίστα `ALLOWED_HOSTS` αν χρησιμοποιείτε το cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Δημιουργία μιας βάσης δεδομένων + +Υπάρχουν πολλές διαφορετικές βάσεις δεδομένων που μπορούν να αποθηκεύσουν δεδομένα για την σελίδα σας. Θα χρησιμοποιήσουμε την προεπιλεγμένη, `sqlite3`. + +Αυτό έχει ήδη δηλωθεί στο αρχείο `mysite/settings.py`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +Για να δημιουργήσετε μία βάση δεδομένων για το blog σας, ας εκτελέσουμε το ακόλουθο στην κονσόλα: `python manage.py migrate` ( χρειάζεται να είμαστε στον φάκελο `djangogirls` που περιέχει το αρχείο `manage.py`). Αν αυτό πάει καλά, θα πρέπει να δείτε κάτι σαν αυτό: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... ΟΚ + + +Και τελειώσαμε! Ώρα να ξεκινήσουμε τον server και να δούμε εάν η ιστοσελίδα μας λειτουργεί! + +## Εκκίνηση του development server + +Θα πρέπει να είστε στον φάκελο που περιέχει το αρχείο `manage.py` (στον φάκελο `djangogirls`). Στην κονσόλα, μπορούμε να ξεκινήσουμε τον server εκτελώντας `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Εάν είστε σε ένα Chromebook, χρησιμοποιείστε αυτή την εντολή: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> Είδαμε πως λειτουργούν οι web servers στο κεφάλαιο **Πως λειτουργεί το internet**. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/el-GR/django_templates/README.md b/el-GR/django_templates/README.md new file mode 100644 index 00000000000..f52e9840338 --- /dev/null +++ b/el-GR/django_templates/README.md @@ -0,0 +1,108 @@ +# Django templates + +Ήρθε η ώρα να παρουσιάσουμε ορισμένα δεδομένα! Το Django μας δίνει κάποια προεγκατεστημένα **template tags**. + +## Τι είναι τα template tags; + +Βλέπετε, στην HTML δεν μπορείτε να γράψετε κώδικα σε Python επειδή οι browsers δεν καταλαβαίνουν αυτή τη γλώσσα. Εκείνοι ξέρουν μόνο HTML, CSS και Javascript. Ξέρουμε ότι η HTML είναι στατική γλώσσα ενώ η Python περισσότερο δυναμική. + +Τα **Django template tags** μας επιτρέπουν να μεταφέρουμε πράγματα της Python μέσα στην HTML, ούτως ώστε να χτίσετε δυναμικές ιστοσελίδες γρηγορότερα. Τέλεια! + +## Template προβολή λίστας των post + +Σε προηγούμενο κεφάλαιο δώσαμε στο template μας μια λίστα από posts μέσα σε μια μεταβλητή με το όνομα `posts`. Τώρα θα την προβάλουμε στην HTML. Άλλωστε αυτό θέλαμε να κάνουμε από την αρχή. + +Για να εκτυπώσουμε μια μεταβλητή μέσα στα Django templates, χρησιμοποιούμε διπλές αγκύλες ({% raw %}{{ }}{% endraw %}) με το όνομα της μεταβλητής ανάμεσα: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Δοκιμάστε αυτό μέσα στο template `blog/templates/blog/post_list.html`. Ανοίξτε το και αντικαταστήστε τα πάντα από το δεύτερο `
` to the third `
` με το `{{ posts }}`. Αποθηκεύστε το αρχείο και ανανεώστε τη σελίδα για να δείτε τα αποτελέσματα: + +![Σχήμα 13.1](images/step1.png) + +Όπως βλέπετε, το μόνο που έχουμε είναι το εξής: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +Αυτό σημαίνει ότι το Django το εκλαμβάνει ως μια λίστα από objects. Θυμηθείτε στο κεφάλαιο **Εισαγωγή στην Python** πως προβάλαμε λίστες; Ναι, με επαναλήψεις! Στα Django template το κάνετε ως εξής: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Δοκιμάστε αυτό στο template. + +![Σχήμα 13.2](images/step2.png) + +Δούλεψε! Αλλά θέλουμε τα posts μα εμφανίζονται όπως τα στατικά posts που φτιάξαμε νωρίτερα στο κεφάλαιο **Εισαγωγή στην HTML**. Μπορείτε να μιξάρετε HTML και template tags μαζί. Έτσι, το `body` θα μοιάζει κάπως έτσι: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Οτιδήποτε βάζετε ανάμεσα στο `{% for %}` και το `{% endfor %}` θα επαναληφθεί για κάθε object στη λίστα. Ανανεώστε τη σελίδα:{% endraw %} + +![Σχήμα 13.3](images/step3.png) + +Παρατηρήσατε ότι χρησιμοποιούμε έναν διαφορετικό τρόπο πρόσβασης αυτή τη φορά (`{{ post.title }}` ή `{{ post.text }}`); Αποκτούμε πρόσβαση στα δεδομένα κάθε πεδίου που είναι ορισμένα στο μοντέλο `Post`. Επίσης, η κάθετη γραμμή `|linebreaksbr` φιλτράρει το κείμενο του posts όπου μετατρέπει τις αλλαγές γραμμής σε παράγράφους. + +## Ένα ακόμα πράγμα + +Θα ήταν καλό να βλέπαμε αν το site σας εξακολουθεί να λειτουργεί ακόμα στο internet, σωστά; Ας το κάνουμε deploy στο PythonAnywhere για ακόμη μια φορά. Παρακάτω φαίνεται μια περίληψη των βημάτων… + +* Πρώτα κάντε push τον κώδικα σας στο GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Έπειτα συνδεθείτε στο [PythonAnywhere](https://www.pythonanywhere.com/consoles/), μεταβείτε στο **Bash console** (ή ανοίξτε ένα νέο) και τρέξτε: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Θυμηθείτε να αντικαταστήσετε με το ``πραγματικό όνομα χρήστη σας του PythonAnywhere χωρίς τα <>) + +* Τέλος, πηγαίνετε στο ["Web" page](https://www.pythonanywhere.com/web_app_setup/) και κλικάρετε **Reload** στην εφαρμογή σας. (Για να δείτε άλλες σελίδες του PythonAnywhere από την κονσόλα χρησιμοποιήστε το κουμπί του μενού στην πάνω δεξιά γωνία). Η αλλαγή σας θα πρέπει να φαίνεται στο https://subdomain.pythonanywhere.com. Δείτε το στο browser! Δεν πειράζει αν τα posts στο PythonAnywhere δεν είναι τα ίδια με τα posts που εμφανίζονται τοπικά στον υπολογιστή σας. Οι βάσεις δεδομένων στον τοπικό υπολογιστή σας και στο PythonAnywhere δεν είναι συγχρονισμένες μεταξύ τους. + +Συγχαρητήρια! Τώρα προχωρήστε και προσθέστε μερικά posts μέσω του Django admin (θυμηθείτε να προσθέσετε το published_date! -ημερομηνία δημοσίευσης). Σιγουρευτείτε ότι βρίσκεστε στο Django admin της ιστοσελίδας pythonanywhere, https://subdomain.pythonanywhere.com/admin. Έπειτα, ανανεώστε τη σελίδα και δείτε αν αυτά τα posts εμφανίστηκαν. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Σχήμα 13.4](images/donut.png) \ No newline at end of file diff --git a/el-GR/django_urls/README.md b/el-GR/django_urls/README.md new file mode 100644 index 00000000000..6f279ae6908 --- /dev/null +++ b/el-GR/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +Είμαστε έτοιμοι να χτίσουμε την πρώτη μας σελίδα: μια αρχική σελίδα (homepage) για το blog μας! Αλλά πρώτα πρέπει να μάθουμε λίγα πράγματα για τα Django URLs. + +## Τι είναι ένα URL; + +Ένα URL είναι μια διεύθυνση ιστού. Μπορείτε να δείτε ένα URL κάθε φορά που επισκέπτεστε μια σελίδα. Είναι ορατό στην γραμμή διεύθυνσης. (Ναι! `127.0.0.1:8000` είναι ένα URL! Και το `https://djangogirls.org` είναι, επίσης, ένα URL.) + +![URL](images/url.png) + +Κάθε σελίδα στο ιντερνετ χρειάζεται το δικό της URL. Με αυτό τον τρόπο η εφαρμογή σας θα ξέρει τι να δείξει στον χρήστη που ανοίγει αυτό το URL. Στο Django, χρησιμοποιούμε κάτι που το ονομάζουμε `URLconf` (URL configuration). Το URLconf είναι ένα σετ από μοτίβα που το Django θα προσπαθήσει να ταιριάξει με το ζητούμενο URL ούτως ώστε να βρει το κατάλληλο view. + +## Πως δουλεύουν τα URLs στο Django; + +Ας ανοίξουμε το αρχείο `mysite/urls.py` και να δούμε τι έχει μέσα: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +Όπως βλέπετε, το Django έχει γράψει μέσα κάποια πράγματα για εμάς. + +Οι γραμμές μεταξύ των τριπλών εισαγωγικών (`'''` ή `"""`) ονομάζονται docstrings. Μπορείτε να τα γράψετε στην αρχή κάθε Python αρχείου, κλάσης, μεθόδου ή συνάρτησης για να περιγράψετε το τι κάνει. Δεν θα εκτελεστούν από την Python. + +Το admin URL, το οποίο επισκεφτήκατε σε προηγούμενο κεφάλαιο, είναι ήδη εκεί: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +Η γραμμή αυτή σημαίνει ότι για κάθε URL που ξεκινά με τη λέξη `admin/`, το Django θα ψάξει να βρει το αντίστοιχο *view*. Σε αυτή την περίπτωση συμπεριλαμβάνουμε αρκετά admin URLs ούτως ώστε να μην εμφανίζονται όλα σε αυτό το αρχείο. Είναι περισσότερο ευανάγνωστο κατ' αυτό τον τρόπο. + +## Το πρώτο σας Django URL! + +Ώρα να δημιουργήσουμε το πρώτο σας URL! Θέλουμε η διεύθυνση 'http://127.0.0.1:8000/' να είναι η αρχική μας σελίδα για το blog, η οποία θα εμφανίζει όλα τα posts. + +Θέλουμε, επίσης, να κρατήσουμε το αρχείο `mysite/urls.py` καθαρό. Οπότε, θα κάνουμε import τα URLs από το `blog` application στο αρχείο `mysite/urls.py`. + +Πηγαίνετε λοιπόν, και προσθέστε αυτή τη γραμμή στο αρχείο `blog.urls`. Θα χρειαστεί, επίσης, να αλλάξετε την γραμμή `from django.urls…` επειδή χρησιμοποιούμε την συνάρτηση `include`. Επομένως, θα χρειαστεί να προσθέσετε αυτή τη γραμμή. + +Το αρχείο σας `mysite/urls.py` θα μοιάζει κάπως έτσι: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Το Django, τώρα, θα ανακατευθύνει οτιδήποτε έρχεται στο 'http://127.0.0.1:8000/' προς το αρχείο `blog.urls` και από κει και πέρα θα πράττει αναλόγως. + +## blog.urls + +Δημιουργήστε ένα κενό αρχείο `urls.py` μέσα στο φάκελο `blog` και ανοίξτε το. Τέλεια! Προσθέστε αυτές τις δύο γραμμές: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Εδώ κάνουμε import τη συνάρτηση `path` του Django και όλα τα `views` από το `blog` application. (Δεν κάποια views ακόμα αλλά θα φτάσουμε εκεί σε λίγο!) + +Μετά από αυτό, μπορούμε να προσθέσουμε το πρώτο μας URL μοτίβο (URL pattern): + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +Όπως μπορείτε να δείτε, αναθέτουμε ένα `view` με το όνομα `post_list` στο πηγαίο URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. Αυτό το μοτίβο θα πει στο Django ότι το view `views.post_list` είναι το σωστό μέρος να πας αν κάποιος επισκεφτεί τη διεύθυνση 'http://127.0.0.1:8000/'. + +Το τελευταίο μέρος, `name='post_list'`, είναι το όνομα του URL το οποίο θα χρησιμοποιηθεί για να αναγνωρίσουμε αυτό το URL. Αυτό μπορεί να είναι το ίσιο όπως το όνομα του view αλλά μπορεί να είναι κάτι τελείως το διαφορετικό αν θέλετε. Θα χρησιμοποιούμε τα URLs με όνομα (named URLs) αργότερα στο project, οπότε είναι σημαντικό να ονομάσετε κάθε URL στην εφαρμογή σας. Θα προσπαθήσουμε, επίσης, να κρατήσουμε τα ονόματα μοναδικά μεταξύ τους και εύκολα να τα θυμόμαστε. + +Αν προσπαθήσετε να επισκεφτείτε τη διεύθυνση http://127.0.0.1:8000/, τότε θα δείτε ένα σφάλμα τύπου 'web page not available'. Αυτό προκύπτει επειδή ο server (θυμάστε όταν γράψατε `runserver`?) δεν τρέχει. Δείτε στην κονσόλα που έτρεχε ο server σας και δείτε το γιατί. + +![Σφάλμα](images/error1.png) + +Η κονσόλα, σας εμφάνισε σφάλμα αλλά μην ανησυχείτε. Είναι στην ουσία πολύ χρήσιμο: σας λέει **no attribute 'post_list'**. Αυτό είναι το όνομα του *view* το οποίο προσπαθεί να βρει και να χρησιμοποιήσει το Django αλλά δεν το έχουμε δημιουργήσει ακόμα. Σε αυτό το σημείο, ούτε η σελίδα `/admin/` δεν θα λειτουργεί. Μην ανησυχείτε. Θα φτάσουμε και εκεί. Αν δείτε κάποιο διαφορετικό σφάλμα προσπαθείστε να επανεκκινήσετε τον τοπικό server σας. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/el-GR/django_views/README.md b/el-GR/django_views/README.md new file mode 100644 index 00000000000..1c4f2f1358f --- /dev/null +++ b/el-GR/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – ώρα να δημιουργήσουμε! + +Ώρα να ξεφορτωθούμε το σφάλμα που δημιουργήσαμε στο προηγούμενο κεφάλαιο! :) + +Ένα *view* είναι το μέρος όπου βάζουμε την "λογική" της εφαρμογής μας. Θα ζητήσει πληροφορίες από το μοντέλο μας (`model`) που δημιουργήσαμε νωρίτερα και θα το περάσει στο `template`. Θα δημιουργήσουμε ένα template στο επόμενο κεφάλαιο. Τα views είναι απλώς Python συναρτήσεις οι οποίες είναι ελαφρώς πιο περίπλοκες από αυτές που γράψαμε στο κεφάλαιο **Εισαγωγή στην Python**. + +Τα views τοποθετούνται σε ένα αρχείο (ανα εφαρμογή) με το όνομα `views.py`. Θα προσθέσουμε τα δικά μας *views* στο αρχείο `blog/views.py`. + +## blog/views.py + +Ωραία. Ας ανοίξουμε το αρχείο να δούμε τι έχει μέσα: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Όχι και πολλά πράγματα, ακόμα. + +Θυμηθείτε ότι οι γραμμές που ξεκινούν με δίεση `#` είναι σχόλια. Αγνοούνται πλήρως από την Python. + +Ας δημιουργήσουμε ένα *view* όπως προτείνει και το σχόλιο. Προσθέστε τα επόμενα από κάτω: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Όπως βλέπετε, δημιουργήσαμε μια συνάρτηση (`def`) με το όνομα `post_list` η οποία παίρνει την παράμετρο `request` και επιστρέφει `return` την τιμή που παίρνει από άλλη συνάρτηση, την `render`, η οποία κάνει render ("χτίζει") το template `blog/post_list.html`. + +Αποθηκεύστε το αρχείο και επισκεφτείτε τη σελίδα http://127.0.0.1:8000/ να δούμε τι εμφανίζεται. + +Κι άλλο σφάλμα! Διαβάστε το γιατί: + +![Σφάλμα](images/error.png) + +Αυτή τη φορά δείχνει ότι ο server, τουλάχιστον, τρέχει αλλά κάτι δεν πάει καλά, σωστά; Μην ανησυχείτε. Είναι απλώς μια σελίδα σφάλματος! Όπως ακριβώς τα μηνύματα σφάλματος στην κονσόλα, αυτά τα σφάλματα στον browser είναι στην πραγματικότητα πολύ χρήσιμα. Διαβάζετε ότι *TemplateDoesNotExist*. Ας το φτιάξουμε δημιουργώντας ένα template στο επόμενο κεφάλαιο! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/el-GR/dynamic_data_in_templates/README.md b/el-GR/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..97a8351986c --- /dev/null +++ b/el-GR/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Δυναμικά δεδομένα στα templates + +Μέχρι τώρα έχουμε διαφορετικά κομμάτια έτοιμα να συναρμολογηθούν: το μοντέλο `Post` είναι δηλωμένο στο αρχείο `models.py`, την συνάρτηση `post_list` στο αρχείο `views.py` το template. Αλλά πως θα κάνουμε τα posts να εμφανιστούν στο HTML template; Επειδή αυτό θέλουμε να κάνουμε. Να αντλήσουμε δεδομένα (αποθηκευμένα μοντέλα στη βάση δεδομένων) και να τα παρουσιάσουμε όμορφα μέσα από ένα template, σωστά; + +Αυτό ακριβώς κάνουν τα *views*: συνδέουν τα μοντέλα με τα templates. Μέσα στη συνάρτηση `post_list` *view* πρέπει να προσπελάσουμε τα μοντέλα που θέλουμε και να τα δώσουμε στο template. Μέσα στο *view* αποφασίσαμε τι (μοντέλο) θα εμφανιστεί στο template. + +Ωραία, πως το κάνουμε αυτό; + +Πρέπει να ανοίξουμε το αρχείο `blog/views.py`. Μέχρι τώρα η συνάρτηση `post_list` *view* δείχνει κάπως έτσι: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Θυμάστε όταν είπαμε να συμπεριλαμβάνουμε κώδικα γραμμένο σε διαφορετικά αρχεία; Τώρα είναι η στιγμή να συπεριλάβουμε το μοντέλο που είχαμε γράψει στο αρχείο `models.py`. Θα προσθέσουμε τη γραμμή `from .models import Post`, όπως κάτωθι: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +Η τελεία πριν τη λέξη `models` σημαίνει ο *παρόν φάκελος* ή το *παρόν application*. Και τα δύο αρχεία `views.py` και `models.py` βρίσκονται στον ίδιο φάκελο. Αυτό σημαίνει ότι μπορούμε να χρησιμοποιήσουμε την τελεία `.` και μετά το όνομα του αρχείου (δίχως την κατάληξη `.py`). Έπειτα κάνουμε import το όνομα του μοντέλου, δηλαδή της κλάσης (`Post`). + +Και μετά; Για να εξάγουμε τα posts από το μοντέλο `Post` χρειαζόμαστε κάτι που ονομάζεται `QuerySet`. + +## QuerySet + +Θα πρέπει να είστε ήδη εξοικειωμένοι με τον όρο QuerySet και πως αυτό λειτουργεί. Μιλήσαμε γι'αυτά στο κεφάλαιο [Django ORM (QuerySets)](../django_orm/README.md). + +Οπότε τώρα θέλουμε δημοσιευμένα posts ταξινομημένα κατά `published_date`, σωστά; Αυτό το κάναμε ήδη στο κεφάλαιο με τα QuerySets! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Επομένως, ας ανοίξουμε το αρχείο `blog/views.py` και ας προσθέσουμε αυτό το κομμάτι κώδικα στη συνάρτηση `def post_list(request)`. Αλλά μην παραλείψετε να προσθέσετε `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Παρακαλούμε σημειώστε ότι δημιουργούμε μια *μεταβλητή* για το QuerySet: `posts`. Μεταχειριστείτε τη ως το όνομα του QuerySet. Απο δω και στο εξής μπορούμε να αναφερόμαστε σε αυτό με το όνομα αυτό. + +Στη συνάρτηση `render` έχουμε μια παράμετρο `request` (οτιδήποτε λαμβάνουμε από το χρήστη μέσω του Internet) και άλλη μια ακόμα, εκείνη του αρχείου template (`'blog/post_list.html'`). Η τελευταία παράμετρος `{}`, είναι το σημείο που μπορούμε να προσθέσουμε πράγματα για να τα αξιοποιήσει το template. Χρειαζόμαστε να τους δώσουμε ονόματα (θα μείνουμε με το όνομα `'posts'`). :) Θα δείχνει κάπως έτσι: `{'posts': posts}`. Παρακαλούμε σημειώστε ότι το κομμάτι πριν το `:` είναι ένα string; πρέπει να το περικυκλώσετε με "αυτάκια": `''`. + +Εν τέλει, το αρχείο `blog/views.py` θα δείχνει κάπως έτσι: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Αυτό ήταν! Ήρθε η ώρα να πάμε πίσω στο template και να εμφανίσουμε αυτό το QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/el-GR/extend_your_application/README.md b/el-GR/extend_your_application/README.md new file mode 100644 index 00000000000..9e5d29aba40 --- /dev/null +++ b/el-GR/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Επεκτείνετε την εφαρμογή σας + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Ώρα για εξάσκηση! + +Το πρώτο πράγμα που χρειαζόμαστε στο blog μας είναι, προφανώς, μια σελίδα για το εκάστοτε post (της οποίας η εμφάνιση θα είναι η ίδια για όλα post και το μόνο που θα αλλάζει θα είναι το περιεχόμενο), σωστά; + +Έχουμε ήδη ένα μοντέλο `Post`, έτσι δεν χρειάζεται να προσθέσετε τίποτα στο αρχείο `models.py`. + +## Δημιουργία ενός συνδέσμου template με τις λεπτομέρειες του post + +Θα ξεκινήσουμε με την προσθήκη ενός συνδέσμου στο αρχείο `blog/templates/blog/post_list.html`. Ανοίξτε το. Θα δείχνει κάπως έτσι: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}Θέλουμε να έχουμε έναν σύνδεσμο (link) για κάθε τίτλο του post μέσα στη λίστα ο οποίος όταν κλικάρετε να μεταβαίνει στη σελίδα λεπτομερειών του post. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Ώρα να εξηγήσουμε το μυστηριώδης `{% url 'post_detail' pk=post.pk %}`. Όπως υποψιάζεστε, το `{% %}` σημαίνει ότι χρησιμοποιούμε τα Django template tags. Αυτή τη φορά θα χρησιμοποιήσουμε ένα που δημιουργεί μια διεύθυνση URL για εμάς!{% endraw %} + +Το μέρος `post_detail` σημαίνει ότι θα πρέπει το Django θα περιμένει μια διεύθυνση URL με το όνομα αυτό στο αρχείο `blog/urls.py` με το όνομα=post_detail + +Τι γίνεται όμως με το `pk=post.pk`; `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Τώρα, όταν πάμε στη διεύθυνση http://127.0.0.1:8000 / θα εμφανιστεί σφάλμα (όπως ήταν αναμενόμενο, καθώς δεν έχουμε ακόμη διεύθυνση URL ή κάποιο *view* για το `post_detail`). Αυτό θα μοιάζει κάπως έτσι: + +![Σφάλμα NoReverseMatch](images/no_reverse_match2.png) + +## Δημιουργία ενός URL για τις λεπτομέρειες του post + +Ας δημιουργήσουμε μια διεύθυνση URL στο αρχείο `urls.py` για το `post_detail` *view* μας! + +Θέλουμε οι λεπτομέρειες του πρώτου μας post να εμφανίζονται σε αυτό το **URL**: http://127.0.0.1:8000/θέση/1 / + +Ας δημιουργήσουμε ένα URL μέσα στο αρχείο `blog/urls.py` που θα κατευθύνει το Django στο *view* με το όνομα `post_detail`, που με τη σειρά του θα δείξει ένα ολόκληρο blog post. Ανοίξτε το αρχείο `blog/urls.py` και προσθέστε τη γραμμή `path('post//', views.post_detail, name='post_detail'),` έτσι ώστε το αρχείο να μοιάζει κάπως έτσι: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +Το μέρος `post//` καθορίζει ένα URL μοτίβο. Θα σας το εξηγήσουμε: + +- Το μέρος `post/` σημαίνει ότι το URL θα πρέπει να ξεκινά με τη λέξη **post** ακολουθούμενο από μια κάθετο **/**. Μέχρι τώρα όλα καλά. +- `` – Αυτό το μέρος είναι πιο δύσκολο. Σημαίνει ότι το Django περιμένει έναν ακέραιο όπου με την σειρά του θα το μεταφέρει ως παράμετρο με το όνομα `pk` στο αντίστοιχο view. +- `/` – έπειτα χρειαζόματε άλλη μια κάθετο **/** πριν να κλείσει το URL. + +Αυτό σημαίνει ότι αν μεταβείτε στο `http://127.0.0.1:8000/post/5/` στον browser σας, το Django θα καταλάβει ότι ψάχνετε το *view* με το όνομα `post_detail` και θα μεταφέρει την πληροφορία του `pk` που ισούται με το `5` σε αυτό το *view*. + +Ωραία. Προσθέσαμε ένα νέο URL μοτίβο στο αρχείο `blog/urls.py`! Ας ανανεώσουμε τη σελίδα: http://127.0.0.1:8000/ Μπαμ! Ο server σταμάτησε να τρέχει ξανά. Ρίξτε μια ματιά στην κονσόλα. Όπως ήταν αναμενόμενο, υπάρχει ακόμα ένα σφάλμα! + +![AttributeError](images/attribute_error2.png) + +Θυμάστε το επόμενο βήμα; Προσθήκη ενός view! + +## Προσθήκη ενός view για τις λεπτομέρειες του post + +Αυτή τη φορά το *view* δέχεται μια έξτρα παράμετρο, το `pk`. Το *view* μας χρειάζεται με κάποιο τρόπο να αιχμαλωτίσει αυτή την παράμετρο, σωστά; Έτσι, λοιπόν, θα ορίσουμε την συνάρτηση μας ως `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Τώρα, θέλουμε να πάρουμε ένα και μόνο ένα post. Για να το κάνουμε αυτό, μπορούμε να χρησιμοποιήσουμε τα querysets, όπως παρακάτω: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +Αλλά αυτός ο κώδικας έχει πρόβλημα. Αν δεν υπάρχει κάποιο `Post` με το δεδομένο `primary key` (`pk`) θα έχουμε ένα άσχημο σφάλμα! + +![Σφάλμα DoesNotExist](images/does_not_exist2.png) + +Δεν το θέλουμε αυτό! Αλλά ευτυχώς το Django περιλαμβάνει με κάτι που θα μας φανεί χρήσιμο: `get_object_or_404`. Σε αυτή την περίπτωση δεν υπάρχει κάποιο `Post` με αυτό το `pk`, θα εμφανίσει μια πολύ πιο όμορφη σελίδα, την σελίδα `Page Not Found 404`. + +![Page not found](images/404_2.png) + +Τα καλά νέα είναι ότι μπορείτε να δημιουργήσετε τη δική σας σελίδα `Page not found` και να την κάνετε όσο όμορφη θέλετε. Αλλά δεν είναι εξαιρετικά σημαντικό αυτή τη στιγμή, οπότε θα το παραλείψουμε τώρα. + +Ωραία, ώρα να προσθέσουμε ένα *view* στο αρχείο `views.py`! + +Στο αρχείο `blog/urls.py` δημιουργήσαμε ένα URL με το όνομα `post_detail`, που αναφέρεται σε ένα view με το όνομα `views.post_detail`. Αυτό σημαίνει ότι το Django θα περιμένει να υπάρχει μια συνάρτηση με το όνομα `post_detail` μέσα στο αρχείο `blog/views.py`. + +Ανοίξτε το αρχείο`blog/views.py` και προσθέστε τις ακόλουθες γραμμές μαζί με τις γραμμές `from`: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +Και στο τέλος του αρχείου θα προσθέσουμε το *view*: + +{% filename %}blog/views.py{% endfilename %} + +```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/ + +![view για την λίστα των post](images/post_list2.png) + +Δούλεψε! Αλλά τι συμβαίνει όταν κλικάρετε στον σύνδεσμο σε κάποιον τίτλο ενός post; + +![Σφάλμα TemplateDoesNotExist](images/template_does_not_exist2.png) + +Ω όχι! Άλλο ένα άλλο σφάλμα! Αλλά ήδη γνωρίζουμε πώς να το αντιμετωπίσουμε, έτσι; Πρέπει να προσθέσουμε ένα template! + +## Δημιουργία template για τις λεπτομέρειες του post + +Θα δημιουργήσoυμε ένα αρχείο μέσα στο φάκελο `blog/πρότυπα/blog` με το όνομα `post_detail.html`. Ανοίξτε το. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +Για μια ακόμη φορά θα επεκτείνουμε το template `base.html`. Στο block`content` θέλουμε να εμφανίσουμε την ημ/νια έκδοσης του post (αν υπάρχει) τον τίτλο και το κυρίως κείμενο. Αλλά θα πρέπει να συζητήσουμε ορισμένα σημαντικά πράγματα, έτσι; + +{% raw %}`{% if ... %} ... {% endif %}` είναι ένα template tag που μας επιτρέπει να ελέγξουμε κάτι - με άλλα λόγια είναι μια συνθήκη. (Θυμάστε το `if ... else ..` από το κεφάλαιο **Εισαγωγή στην Python**?) Σε αυτό το σενάριο θέλουμε να δούμε αν το πεδίο `published_date` του post έχει κάποια τιμή.{% endraw %} + +Ωραία, μπορούμε να ανανεώσουμε τη σελίδα και να δούμε, για αρχή, αν το σφάλμα `TemplateDoesNotExist` έχει φύγει. + +![Σελίδα λεπτομέρειας του post](images/post_detail2.png) + +Ναι! Έφυγε! + +# Ώρα για deploy! + +Θα ήταν καλό να δούμε εάν η σελίδα σας εξακολουθεί να λειτουργεί στο PythonAnywhere, σωστά; Ας δοκιμάσουμε να το κάνουμε deploy ξανά. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Θυμηθείτε να αντικαταστήσετε με το ``πραγματικό όνομα χρήστη σας του PythonAnywhere χωρίς τα <>) + +## Ενημέρωση των στατικών αρχείων στο διακομιστή + +Οι διακομιστές όπως το PythonAnywhere τους αρέσει να διαχειρίζονται τα «στατικά αρχεία» (όπως τα αρχεία CSS) διαφορετικά από τα αρχεία της Python επειδή μπορεί να βελτιστοποιηθούν ούτως ώστε να φορτώνονται πιο γρήγορα. Ως αποτέλεσμα, κάθε φορά που μπορούμε να κάνουμε αλλαγές στα αρχεία CSS, θα πρέπει να εκτελούμε μια πρόσθετη εντολή στο διακομιστή η οποία του λέει να τα ενημερώσει. Η εντολή ονομάζεται `collectstatic`. + +Ξεκινήστε με το να ενεργοποιήσετε το virtualenv σας, αν δεν είναι ήδη ενεργό (το PythonAnywhere χρησιμοποιεί μια εντολή που ονομάζεται `workon` για να γίνει αυτό, είναι ακριβώς σαν την εντολή `source myenv/bin/activate` που χρησιμοποιείτε στον υπολογιστή σας): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +Η εντολή `manage.py collectstatic` είναι λίγο σαν την `manage.py migrate`. Κάνουμε κάποιες αλλαγές στον κώδικα και στη συνέχεια λέμε στο Django να *εφαρμόσει* αυτές τις αλλαγές είτε στον αντίστοιχο φάκελο στατικών αρχείων του server είτε στη βάση δεδομένων. + +Σε κάθε περίπτωση, είμαστε τώρα έτοιμοι να κλικάρουμε ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (από το κουμπί του μενού στην επάνω δεξιά μεριά της κονσόλας) και κλικάρουμε στο **Reload**. Δείτε τη σελίδα https://subdomain.pythonanywhere.com με το αποτέλεσμα. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/el-GR/how_the_internet_works/README.md b/el-GR/how_the_internet_works/README.md new file mode 100644 index 00000000000..726bc1842a6 --- /dev/null +++ b/el-GR/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# Πως λειτουργεί το internet + +> Για τους αναγνώστες στο σπίτι: αυτή η ενότητα καλύπτεται στο βίντεο [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc). +> +> Αυτό το κεφάλαιο είναι εμπνευσμένο από την ομιλία της Jessica McKellar με τίτλο "How the Internet works" (http://web.mit.edu/jesstess/www/). + +Στοιχηματίζουμε ότι δουλεύετε το Internet κάθε μέρα. Αλλά ξέρετε τι συμβαίνει όταν πληκτρολογείτε μια διεύθυνση όπως https://djangogirls.org στο browser σας και μετά πατήσετε `enter`; + +The first thing you need to understand is that a website consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Οι web browsers σχεδιάστηκαν για να κατανοούν αυτό τον κώδικα, να ακολουθούν τις εντολές του και να παρουσιάζουν αυτά τα αρχεία από τα οποία είναι φτιαγμένα το website σας με τον τρόπο που εσείς θέλετε. + +Όπως με κάθε αρχείο, χρειαζόμαστε να αποθηκεύουμε τα HTML αρχεία κάπου στον σκληρό δίσκο. Για το Internet, χρησιμοποιούμε ειδικούς υπολογιστές γι'αυτό, με το όνομα *servers*. Δεν έχουν οθόνη, ποντίκι ή πληκτρολόγιο επειδή ο μοναδικός σκοπός τους είναι να αποθηκεύουν δεδομένα και να τα εξυπηρετούν. Γι' αυτό το λόγο ονομάζονται *εξυπηρετητές*. Επειδή *εξυπηρετούν την μεταφορά* δεδομένων. + +ΟΚ, αλλά θέλετε να μάθετε πως φαίνεται το Internet, σωστά; + +Ζωγραφίσαμε μια εικόνα! Φαίνεται κάπως έτσι: + +![Σχήμα 1.1](images/internet_1.png) + +Λίγο χαοτική, έτσι; Στην πραγματικότητα είναι ένα δίκτυο συνδεδεμένων συσκευών (των προαναφερομένων *servers*). Εκατοντάδες χιλιάδες συσκευές! Πολλά πολλά χιλιόμετρα καλωδίων γύρω από ολόκληρο τον κόσμο! Μπορείτε να επισκεφτείτε την ιστοσελίδα του Submarine Cable Map (http://submarinecablemap.com) και να δείτε πόσο περίπλοκο είναι το δίκτυο. Παρακάτω φαίνεται ένα στιγμιότυπο από το website: + +![Σχήμα 1.2](images/internet_3.png) + +Φανταστικό, έτσι; Αλλά δεν είναι δυνατόν να έχουμε καλώδια ανάμεσα σε κάθε ζευγάρι συσκευών που είναι συνδεδμένο στο Internet. Οπότε, για να συνδεθούμε με μία συσκευή (για παράδειγμα, αυτή που είναι αποθηκευμένο το site https://djangogirls.org) θα χρειαστεί να περάσουμε ένα αίτημα (request) μέσα από πολλές πολλές διαφορετικές συσκευές. + +Δείχνει κάπως έτσι: + +![Σχήμα 1.3](images/internet_2.png) + +Φανταστείτε ότι όταν πληκτρολογείτε https://djangogirls.org, στέλνετε ένα γράμμα που λέει: "Αγαπητά Django Girls, θα ήθελα να δω την σελίδα djangogirls.org. Στείλτε τη μου, παρακαλώ!" + +Το γράμμα σας πηγαίνει στο πλησιέστερο ταχυδρομικό γραφείο. Μετά το γράμμα σας πηγαίνει σε άλλο γραφείο που είναι πιο κοντά στον παραλήπτη, μετά σε άλλον κοκ μέχρις ότου φτάσει στον προορισμό του. Το μόνο μοναδικό πράγμα είναι ότι αν στέλνετε πολλά γράμματα (*data packets*) στο ίδιο σημείο, τότε ίσως φτάσουν στον προορισμό τους μέσα από διαφορετικές διαδρομές και ταχυδρομικά γραφεία (*routers*). Αυτό εξαρτάται από το πως είναι ταξινομημένα σε κάθε γραφείο. + +![Σχήμα 1.4](images/internet_4.png) + +Έτσι λειτουργεί. Μπορείτε να στείλετε μηνύματα και να περιμένετε κάποια απάντηση. Αντί για χαρτί και στυλό χρησιμοποιείτε byte δεδομένων αλλά η ιδέα είναι η ίδια! + +Αντί για διευθύνσεις με όνομα οδού, πόλη, ταχυδρομικό κώδικα και χώρα, χρησιμοποιούμε διευθύνσεις IP. Ο υπολογιστής σας ρωτά πρώτα το DNS (Domain Name System) για να μεταφραστεί η λέξη djangogirls.org σε μια διεύθυνση IP. Λειτουργεί λίγο σαν τους παλιούς τηλεφωνικούς καταλόγους όπου μπορείτε να αναζητήσετε το όνομα του ατόμου που θέλετε να επικοινωνήσετε και να βρείτε τον αριθμό τηλεφώνου και τη διεύθυνση τους. + +Όταν στέλνετε ένα γράμμα, πρέπει να έχει ορισμένα χαρακτηριστικά πρέπει για να παραδοθεί σωστά: μια διεύθυνση, μια σφραγίδα, κλπ. Χρησιμοποιείτε επίσης μια γλώσσα που κατανοεί ο παραλήπτης, σωστά; Το ίδιο ισχύει για τα *data packets* που μπορείτε να στείλετε για να δείτε μια ιστοσελίδα. Χρησιμοποιούμε ένα πρωτόκολλο που ονομάζεται HTTP (Hypertext Transfer Protocol). + +Έτσι, βασικά, όταν έχετε μια ιστοσελίδα, θα πρέπει να έχετε έναν *server* (συσκευή). Όταν ο *server* λαμβάνει μια εισερχόμενη *αίτηση* (σε ένα γράμμα), στέλνει πίσω την ιστοσελίδα σας (σε άλλη επιστολή). + +Δεδομένου ότι αυτό είναι ένας Django οδηγός, μπορείτε να ρωτήσετε τι κάνει Django. Όταν στέλνετε μια απάντηση, δεν θέλετε να στέλνετε την ίδια σε όλους. Είναι πολύ καλύτερα αν τα γράμματα είναι εξατομικευμένα, ειδικά για το πρόσωπο που έχει γράψει αποκλειστικά για εσάς, σωστά; Το Django, σας βοηθά με τη δημιουργία αυτών των εξατομικευμένων, ενδιαφέροντων γραμμάτων. :) + +Αρκετά μιλήσαμε. Πάμε να δημιουργήσουμε! \ No newline at end of file diff --git a/el-GR/html/README.md b/el-GR/html/README.md new file mode 100644 index 00000000000..32de9f995f3 --- /dev/null +++ b/el-GR/html/README.md @@ -0,0 +1,227 @@ +# Εισαγωγή στην HTML + +Ίσως αναρρωτιέστε, τι είναι ένα template; + +Ένα template είναι ένα αρχείο που μπορούμε να επαναχρησιμοποιούμε για να παρουσιάζουμε διαφορετικές πληροφορίες μέσα από μια συνεπή μορφή. Για παράδειγμα, θα μπορούσατε να χρησιμοποιήσετε ένα πρότυπο (template) για να σας βοηθήσει να γράψετε μια επιστολή, γιατί αν και κάθε επιστολή μπορεί να περιέχει διαφορετικό μήνυμα και να απευθύνεται σε ένα διαφορετικό πρόσωπο, μερικά σημεία θα μοιραστούν την ίδια μορφή. + +Η μορφή ενός Django template περιγράφεται με μια γλώσσα που ονομάζεται HTML (που είναι η HTML που αναφέραμε στο πρώτο κεφάλαιο, **Πώς λειτουργεί το Internet**). + +## Τι είναι η HTML; + +Η HTML είναι ένας κώδικας που ερμηνεύεται από τον web browser σας – όπως ο Chrome, Firefox ή Safari - για να εμφανιστεί μια ιστοσελίδα στον χρήστη. + +HTML σημαίνει "HyperText Markup Language". Η λέξη **HyperText** σημαίνει ότι είναι ένας τύπος κειμένου που υποστηρίζει υπερ-συνδέσεις μεταξύ των σελιδών. **Markup** σημαίνει ότι έχουμε λάβει ένα έγγραφο και το έχουμε επισημάνει με κώδικα ούτως ώστε να πει κάτι (στην προκειμένη περίπτωση, ένας browser) πώς να ερμηνεύσει τη σελίδα. Ο HTML κώδικας είναι χτισμένος με **tags**, όπου καθένα αρχίζει με `<` και τελειώνει με `>`. Αυτά τα tags αντιπροσωπεύουν τα markup **elements**. + +## Το πρώτο σας template! + +H δημιουργία ενός template σημαίνει τη δημιουργία ενός αρχείου template. Τα πάντα είναι ένα αρχείο, σωστά; Πιθανώς να το έχετε παρατηρήσει αυτό. + +Τα templates αποθηκεύονται στο φάκελο `blog/templates/blog`. Άρα, πρώτα δημιουργήστε έναν φάκελο με το όνομα `templates` μέσα στον φάκελο blog. Στη συνέχεια, δημιουργήστε έναν άλλο φάκελο που ονομάζεται `blog` μέσα στον φάκελο templates: + + blog + └───templates + └───blog + + +(Ίσως να αναρωτηθείτε γιατί χρειαζόμαστε δύο φακέλους που και οι δύο ονομάζονται `blog`. Όπως θα ανακαλύψετε αργότερα, αυτό είναι μια τεχνική ονομασίας που κάνει τη ζωή ευκολότερη όταν τα πράγματα αρχίζουν να περιπλέκονται.) + +Και τώρα δημιουργήστε ένα αρχείο `post_list.html` (απλά αφήστε το κενό για τώρα) μέσα στον φάκελο `blog/templates/blog`. + +Δείτε πώς εμφανίζεται η ιστοσελίδα σας στο: http://127.0.0.1:8000 / + +> Αν παρουσιάζεται ακόμα το σφάλμα `TemplateDoesNotExist`, δοκιμάστε να επανεκκινήσετε τον server σας. Προσπαθήστε να τον σταματήσετε (πιέζοντας Ctrl + C) και επανεκκινήστε τον τρέχοντας την εντολή `python manage.py runserver`. + +![Σχήμα 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Ανοίξτε το νέο αρχείο και προσθέστε τα εξής: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +Οπότε πως φαίνεται τώρα η ιστοσελίδα μας; Επισκεφθείτε το για να μάθετε: http://127.0.0.1:8000/ + +![Σχήμα 11.2](images/step3.png) + +It worked. Nice work there! :) + +* The line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 + +Κάθε σελίδα HTML χωρίζεται σε δύο στοιχεία: το **head** και το **body**. + +* To **head** είναι ένα στοιχείο (element) που περιέχει πληροφορίες σχετικά με το έγγραφο αλλά αυτές οι πληροφορίες δεν εμφανίζονται στην οθόνη. + +* Το **body** είναι ένα στοιχείο που περιέχει όλα τα υπόλοιπα που εμφανίζονται ως μέρος της ιστοσελίδας. + +Χρησιμοποιούμε το tag ``για να πούμε στον browser σχετικά με τη διαμόρφωση της σελίδας και το tag `` για να πούμε για το περιεχόμενο της. + +Για παράδειγμα, μπορείτε να προσθέσετε τίτλο στην ιστοσελίδα σας μέσα από το tag ``, όπως παρακάτω: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Αποθηκεύστε το αρχείο και ανανέωστε την σελίδα σας. + +![Σχήμα 11.3](images/step4.png) + +Παρατηρήσατε πως ο browser κατάλαβε το "Ola's blog" ως τίτλο για την σελίδα σας; Ερμήνευσε το κείμενο `Ola's blog` και το τοποθέτησε στην μπάρα τίτλων του browser σας (το ίδιο κείμενο θα λειτουργήσει και ως όνομα σελιδοδείκτη κλπ). + +Πιθανώς να έχετε παρατηρήσει ότι κάθε tag αντιστοιχίζεται με ένα *tag κλεισίματος*, με μια κάθετο `/` και ότι τα στοιχεία είναι *ένθετα* (δηλαδή δεν μπορείτε να κλείσετε μια συγκεκριμένη ετικέτα μέχρι να έχουν κλείσει όλα αυτά που ήταν μέσα σε αυτό). + +Είναι σαν να βάζουμε πράγματα μέσα σε κουτιά. Έχετε ένα μεγάλο κουτί, ``. Στο εσωτερικό του υπάρχει το `` το οποίο με τη σειρά του περιέχει ακόμα μικρότερα κουτιά: `

`. + +Θα πρέπει να ακολουθείτε αυτούς τους κανόνες *κλεισίματος ετικέτας* και *"φωλιάσματος"* των elements. Αν δεν το κάνετε, ο browser ενδέχεται να μην μπορεί να τα ερμηνεύσει ορθά και η σελίδα να μην εμφανίζεται σωστά. + +## Παραμετροποιώντας το template + +Μπορείτε, τώρα, να διασκεδάσετε λιγάκι και να τροποιήσετε το template σας! Παρακάτω παρουσιάζονται μερικά χρήσιμα tags γι'αυτό: + +* `

A heading

` για επικεφαλίδες +* `

A sub-heading

` για επικεφαλίδες χαμηλότερου επιπέδου +* `

A sub-sub-heading

` …κοκ μέχρι την `
` +* `

Μια παράγραφος κειμένου

` +* `text` δίνει έμφαση στο κείμενο σας +* `text` κάνει τα γράμματα πιο έντονα +* `
` αλλάζει γραμμή (δεν μπορείτε να βάλετε τίποτα ανάμεσα και δεν υπάρχει αντίστοιχο tag που να το κλείνει) +* `link` δημιουργεί έναν σύνδεσμο +* `
  • first item
  • second item
` δημιουργεί μια λίστα, όπως αυτή εδώ που διαβάζετε τώρα! +* `
` ορίζει ένα τμήμα στη σελίδα +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Παρακάτω φαίνεται ένα πλήρες παράδειγμα ενός template. Αντιγράψτε-επικολλήστε το μέσα στο αρχείο `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +Δίνει αυτή την αίσθηση: + +![Σχήμα 11.4](images/step6.png) + +Ναιιι! Αλλά μέχρι στιγμής, το template μας εμφανίζει **τις ίδιες πληροφορίες** – ενώ προηγουμένως μιλούσαμε για templates που μας επέτρεπαν να εμφανίσουμε **διαφορετικές/δυναμικές** πληροφορίες με την **ίδια μορφή**. + +Αυτό που θέλουμε να κάνουμε είναι να εμφανίσουμε πραγματικά posts τα οποία θα τα προσθέτουμε μέσω του Django admin. Και αυτό ακριβώς θα κάνουμε μετά. + +## Ένα πράγμα ακόμα: ώρα να το ανεβάσετε! + +Θα ήταν καλό να το δούμε όλο αυτό στο internet, σωστά; Ας κάνουμε άλλο ένα deploy στο PythonAnywhere: + +### Κάντε commit και έπειτα push τον κώδικα σας στο GitHub + +Πρώτ'απ'όλα ας δούμε ποια αρχεία έχουν αλλάξει από την τελευταία φορά που κάναμε deploy (τρέξτε αυτές τις εντολές τοπικά, όχι στο PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Σιγουρευτείτε ότι βρίσκεστε μέσα στο φάκελο `djangogirls` και ας πούμε στο `git` να συμπεριλάβει όλες τις αλλαγές μέσα σε αυτό το φάκελο: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +Πριν ανεβάσουμε όλα τα αρχεία, ας δούμε τι επρόκειτο να ανεβάσει το `git` (όλα τα αρχεία που επρόκειτο να ανεβούν από το `git` θα εμφανίζονται με πράσινο χρώμα): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Σχεδόν φτάσαμε. Τώρα είναι η ώρα να του πούμε να αποθηκεύσει αυτή την αλλαγή στο ιστορικό του. Θα του δώσουμε ένα "commit message" όπου θα περιγράψουμε τι άλλαξε. Μπορείτε να γράψετε ότι θέλετε σε αυτό το σημείο αλλά είναι χρήσιμο να γράψετε κάτι περιγραφικό ούτως ώστε να το θυμάστε στο μέλλον. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "Changed the HTML for the site." + + +> **Note** Make sure you use double quotes around the commit message. + +Μόλις τελειώσουμε με αυτό, θα ανεβάσουμε (push) τις αλλαγές μας στο GitHub: + +{% filename %}command-line{% endfilename %} + + $ git push + + +### Κάντε pull τον νέο σας κώδικα στο PythonAnywhere και ανανεώστε την εφαρμογή + +* Έπειτα συνδεθείτε στο [PythonAnywhere](https://www.pythonanywhere.com/consoles/), μεταβείτε στο **Bash console** (ή ανοίξτε ένα νέο) και τρέξτε: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. Αν θέλετε να δείτε ότι ολοκληρώθηκε, μεταβείτε στη σελίδα **"Files" page** και δείτε τον κώδικα σας στο PythonAnywhere (μπορείτε να ανοίξετε και άλλες σελίδες του PythonAnywhere από το κουμπί του μενού στην σελίδα της κονσόλας). + +* Τέλος, πηγαίνετε στο ["Web" page](https://www.pythonanywhere.com/web_app_setup/) και κλικάρετε **Reload** στην εφαρμογή σας. + +Οι αλλαγές θα πρέπει να είναι ορατές τώρα! Πηγαίνετε και ανανεώστε τη σελίδα στον browser σας. :) \ No newline at end of file diff --git a/el-GR/installation/README.md b/el-GR/installation/README.md new file mode 100644 index 00000000000..6ea2876af00 --- /dev/null +++ b/el-GR/installation/README.md @@ -0,0 +1,68 @@ +# Για σένα που κάνεις το tutorial από το σπίτι + +Αν κάνεις το tutorial στο σπίτι και όχι στο πλαίσιο ενός από τα [Django Girls events](https://djangogirls.org/events/), μπορείς να αγνοήσεις εντελώς αυτό το κεφάλαιο και να πας κατευθείαν στο κεφάλαιο [Πώς δουλεύει το internet](../how_the_internet_works/README.md). + +Αυτό οφείλεται στο γεγονός ότι καλύπτουμε γνωστικά ένα αντικείμενο καθώς το συναντάμε και όχι όλα μαζεμένα. Αυτή είναι μια σελίδα που συγκεντρώνει όλες τις οδηγίες εγκατάστασης σε ένα μέρος (το οποίο είναι χρήσιμο για ορισμένες μορφές των εργαστηρίων). Μπορείτε να διαλέξετε να τα εγκαταστήσετε όλα όσα είναι σε αυτή τη σελίδα αν θέλετε. Αλλά αν θέλετε να μαθαίνετε πράγματα καθώς εγκαθιστάτε πράγματα στον υπολογιστή σας, αγνοήστε αυτό το κεφάλαιο και θα εξηγήσουμε τη διαδικασία εγκατάστασης διαφόρων εργαλείων καθώς τα συναντάμε μπροστά μας. + +Καλή τύχη! + +# Αν παρακαλουθείτε ένα εργαστήριο + +Εάν παρακολουθείτε ένα από τα [Django Girls events](https://djangogirls.org/events/): + +* Το εργαστήριο μπορεί να έχει μια "ομάδα εγκατάστασης" πριν το κυρίως εργαστήριο. Αν ανήκετε στην ομάδα εγκατάστασης, τότε αυτή η σελίδα είναι για εσάς! Ακολουθήστε τις οδηγίες εδώ, για να έχετε όλα όσα χρειάζεστε για το εργαστήριο εγκατεστημένα, με τη βοήθεια των βοηθών αν χρειαστεί. Στη συνέχεια, στο κυρίως εργαστήριο, θα είστε σε θέση να παρακάμψετε τις οδηγίες εγκατάστασης που θα συναντήσετε στον οδηγό. +* Μπορεί να σας έχουν ζητήσει οι διοργανωτές του εργαστηρίου να δοκιμάσετε στο σπίτι να εγκαταστήσετε τα πάντα στον υπολογιστή σας, πριν ξεκινήσει το εργαστήρι. Εάν σας έχει ζητηθεί να το κάνετε αυτό, η σελίδα αυτή είναι για εσάς! Ακολουθήστε τις οδηγίες εδώ, όσο καλύτερα μπορείτε. Στη συνέχεια, στο κυρίως εργαστήριο, όταν φτάνετε σε ένα βήμα εγκατάσταση στον οδηγό, αν δεν έχει συμπεριληφθεί από εμάς μπορείτε να λάβετε βοήθεια από το λεωφορείο. +* Αν το εργαστήριο σας δεν έχει ομάδα εγκατάστασης (ή δεν μπορούσατε να παρευρεθείτε) και οι διοργανωτές δεν σας ζήτησαν να εγκαταστήσετε όσα χρειάζεται πριν φτάσετε, αγνοήστε αυτή τη σελίδα και πηγαίνετε στον κεφάλαιο [Πως δουλεύει το internet](../how_the_internet_works/README.md). Θα εγκαθιστάτε οτιδήποτε χρειάζεται καθώς το συναντάτε στον οδηγό. + +# Εγκατάσταση + +Σε αυτό τον οδηγό θα φτιάξουμε ένα blog. Για να το κάνουμε αυτό, καθώς προχωράμε θα σας ζητηθεί να εγκαταστήσετε διάφορα προγράμματα στον υπολογιστή σας και να δημιουργήσετε μερικούς λογαριασμούς. Αυτή η σελίδα συγκεντρώνει όλες τις εγκαταστάσεις και τις δημιουργίες λογαριασμών σε ένα μέρος (το οποίο είναι χρήσιμο για μερικούς τύπους εργαστηρίων). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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: + +* [Πως λειτουργεί το internet](../how_the_internet_works/README.md) + +* [Εισαγωγή στην γραμμή εντολών](../intro_to_command_line/README.md) + +* [Εισαγωγή στην Python](../python_introduction/README.md) + +* [Τι είναι το 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. \ No newline at end of file diff --git a/el-GR/intro_to_command_line/README.md b/el-GR/intro_to_command_line/README.md new file mode 100644 index 00000000000..99132d95208 --- /dev/null +++ b/el-GR/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Εισαγωγή στην γραμμή εντολών + +> Για τους αναγνώστες στο σπίτι: αυτή η ενότητα καλύπτεται στο βίντεο [Your new friend: Command Line](https://www.youtube.com/watch?v=jvZLWhkzX-8). + +Είναι φοβερό έτσι; Θα γράψετε την πρώτη γραμμή κώδικα σε μερικά λεπτά! :) + +**Αφήστε μας να σας παρουσιάσουμε το νέο σας φίλο πρώτα: τη γραμμή εντολών!** + +Τα επόμενα βήματα θα σας δείξουν πώς να χρησιμοποιήσετε το μαύρο παράθυρο που όλοι οι χάκερ χρησιμοποιούν. Αυτό μπορεί να μοιάζει λίγο τρομακτικό στην αρχή αλλά πραγματικά αυτό είναι απλά ένα prompt σε αναμονή για εντολές από εσάς. + +> **Σημείωση** Παρακαλούμε να σημειώσετε ότι σε όλο το βιβλίο αυτό χρησιμοποιούμε το τους όρους «φάκελος» και «κατάλογος» αλλά στην ουσία είναι το ίδιο πράγμα. + +## Τι είναι η γραμμή εντολών; + +Το παράθυρο, το οποίο συνήθως ονομάζεται **γραμμή εντολών** ή **περιβάλλον γραμμής εντολών**, είναι μια εφαρμογή που βασίζεται σε κείμενο για προβολή, διαχείριση και χειρισμό αρχείων στον υπολογιστή σας. Είναι κάπως σαν το Windows Explorer ή το Finder στα Mac αλλά χωρίς το γραφικό κομμάτι (κουμπιά, βελάκια, σχήματα κλπ). Άλλα ονόματα για την γραμμή εντολών είναι: *cmd*, *CLI*, *prompt*, *console* ή *terminal*. + +## Άνοιγμα της γραμμής εντολών + +Για να πειραματιστείτε πρέπει πρώτα να ανοίξετε μια γραμμή εντολών (ή κονσόλα, πιο σύντομα). + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Η πρώτη σας εντολή (ΝΑΙ!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Βασικά + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Παρόν φάκελος + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Μάθετε περισσότερα σχετικά με μια εντολή + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### Προβολή αρχείων και φακέλων + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM
Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Αλλαγή του τρέχοντος φακέλου + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Δημιουργία φακέλου + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Εξασκηθείτε! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Λύση: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Διαγραφή + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### Έξοδος + +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 + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, huh? :) + +## Περίληψη + +Here is a summary of some useful commands: + +| Εντολή (Windows) | Εντολή (Mac OS / Linux) | Περιγραφή | Παράδειγμα | +| ---------------- | ----------------------- | -------------------------------------- | ------------------------------------------------- | +| exit | exit | κλείσιμο παραθύρου | **exit** | +| cd | cd | αλλαγή φακέλου | **cd test** | +| cd | pwd | προβολή τρέχοντος φακέλου | **cd** (Windows) ή **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (ή del) | rm | διαγραφή αρχείου | **del c:\test\test.txt** | +| rmdir /S | rm -r | διαγραφή φακέλου | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | προβολή βοήθειας για μια εντολή | **cd /?** (Windows) ή **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Είστε έτοιμοι; + +Let's dive into Python! \ No newline at end of file diff --git a/el-GR/intro_to_command_line/open_instructions.md b/el-GR/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..95a4ec5db81 --- /dev/null +++ b/el-GR/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Ανάλογα με την έκδοση των Windows και το πληκτρολόγιό σας, μια από τις παρακάτω επιλογές ανοίγει ένα παράθυρο εντολών (ίσως χρειαστεί να πειραματιστείτε λίγο, αλλά δεν χρειάζεται να δοκιμάσετε όλες αυτές τις προτάσεις): + +- Μεταβείτε στο μενού "Έναρξη" ή στην οθόνη και πληκτρολογήστε "Command Prompt" ("γραμμή εντολών") στο πεδίο αναζήτησης. +- Πηγαίνετε στο Start menu → Windows System → Command Prompt. +- Πηγαίνετε στο Start menu → All Programs → Accessories → Command Prompt. +- Μεταβείτε στην οθόνη έναρξης (Start screen), τοποθετήστε το δείκτη του ποντικιού στην κάτω αριστερή γωνία της οθόνης και κάντε κλικ στο κάτω βέλος που εμφανίζεται (σε μια οθόνη αφής, μετακινείστε το δάχτυλο σας από το κάτω μέρος της οθόνης προς τα επάνω). Η σελίδα "εφαρμογές" (Apps) πρέπει να ανοίξει. Κάντε κλικ στη γραμμή εντολών στην ενότητα Σύστημα των Windows (Windows System). +- Κρατήστε πατημένο το ειδικό πλήκτρο των Windows στο πληκτρολόγιό σας και πατήστε το πλήκτρο "X". Επιλέξτε "γραμμή εντολών" ("Command Prompt") από το αναδυόμενο μενού. +- Κρατήστε πατημένο το πλήκτρο Windows και πατήστε το πλήκτρο "R" για να εμφανιστεί το παράθυρο "εκτέλεση" ("Run"). Πληκτρολογήστε "cmd" στο πλαίσιο και πατήστε το κουμπί ΟΚ. + +![Πληκτρολογήστε "cmd" στο παράθυρο "Run"](../python_installation/images/windows-plus-r.png) + +Αργότερα σε αυτό το tutorial, θα χρειαστεί να έχετε δύο παράθυρα εντολών ανοιχτά την ίδια στιγμή. Ωστόσο, σε ορισμένες εκδόσεις των Windows, αν έχετε ήδη ανοίξει ένα παράθυρο εντολών και προσπαθήσετε να ανοίξετε ένα δεύτερο χρησιμοποιώντας την ίδια μέθοδο, θα οδηγηθείτε στο παράθυρο εντολών που έχετε ήδη ανοίξει. Δοκιμάστε το τώρα στον υπολογιστή σας και δείτε τι συμβαίνει! Εάν σας ανοίξει μόνο ένα παράθυρο εντολών, δοκιμάστε μία από τις άλλες μεθόδους της παραπάνω λίστας. Τουλάχιστον μία από αυτές θα πρέπει να οδηγήσει σε άνοιγμα ενός νέου παραθύρου εντολών. + + + + + +Πηγαίνετε στο Applications → Utilities → Terminal. + + + + + +Το πιο πιθανό να βρίσκεται στο Applications → Accessories → Terminal, or Applications → System → Terminal αλλά εξαρτάται και από το σύστημα. Αν δεν βρίσκεται εκεί, δοκιμάστε να ψάξετε στο Google. :) + + \ No newline at end of file diff --git a/el-GR/python_installation/README.md b/el-GR/python_installation/README.md new file mode 100644 index 00000000000..f085cc8cd00 --- /dev/null +++ b/el-GR/python_installation/README.md @@ -0,0 +1,15 @@ +# Ας ξεκινήσουμε με την Python + +Είμαστε επιτέλους εδώ! + +Αλλά πρώτα θα θέλαμε να σας εξηγήσουμε τι είναι η Python. Η Python είναι μια πολύ δημοφιλής γλώσσα προγραμματισμού η οποία μπορεί να χρησιμοποιηθεί σε πολλούς τομείς όπως δημιουργία ιστοσελίδων, παιχνίδια, επιστημονικό λογισμικό, γραφικά και πολλά πολλά άλλα. + +Η Python δημιουργήθηκε στα τέλη της δεκαετίας του 1980 και ο κύριος σκοπός της είναι να είναι ευανάγνωστη από ανθρώπους (και όχι από μηχανές!). Γι'αυτό το λόγο φαίνεται απλούστερη από άλλες γλώσσες προγραμματισμού, αλλά μην ανησυχείτε. Η Python είναι πραγματικά δυνατή! + +# Εγκατάσταση Python + +> **Σημείωση** Αν χρησιμοποιείτε Chromebook, μεταβείτε στο κεφάλαιο [Εγκατάσταση Chromebook](../chromebook_setup/README.md). +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/el-GR/python_installation/instructions.md b/el-GR/python_installation/instructions.md new file mode 100644 index 00000000000..59dacebabc1 --- /dev/null +++ b/el-GR/python_installation/instructions.md @@ -0,0 +1,117 @@ +> Για τους αναγνώστες στο σπίτι: αυτό το κεφάλαιο καλύπτεται στο βίντεο [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA). +> +> Αυτή η ενότητα βασίζεται σε tutorials από tην κοινότητα Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Το Django είναι γραμμένο σε Python. Χρειαζόμαστε την Python για να κάνουμε το οτιδήποτε στο Django. Ακόμη και να το εγκαταστήσουμε. Ας ξεκινήσουμε εγκαθιστώντας την Python! Θέλουμε να εγκαταστήσετε την τελευταία έκδοση της Python 3. Αν έχετε κάποια παλαιότερη έκδοση θα θέλαμε να την αναβαθμίσετε. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Πιέστε το κουμπί των Windows (δίπλα από το αριστερό Alt) και το Pause/Break ταυτόχρονα. +* Ανοίξτε τον πίνακα ελέγχου (Control Panel) από το Windows μενού και περιηγηθείτε στο System & Security, έπειτα επιλέξτε System +* Πιέστε το πλήκτρο των Windows και έπειτα περιηγηθείτε στο Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Κατεβάστε το αρχείο *Mac OS X 64-bit/32-bit installer*, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/el-GR/python_introduction/README.md b/el-GR/python_introduction/README.md new file mode 100644 index 00000000000..f0f1f532da0 --- /dev/null +++ b/el-GR/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Εισαγωγή στην Python + +> Μέρος αυτού του κεφαλαίου είναι βασισμένο στους οδηγούς από την κοινότητα Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Ας γράψουμε λίγο κώδικα! + +## Παράθυρο εντολών Python + +> Για τους αναγνώστες στο σπίτι: αυτό το μέρος που καλύπτεται από το βίντεο [Python Basics: Integers, Strings, Lists, Variables and Errors](https://www.youtube.com/watch?v=MO63L4s-20U). + +Για να αρχίσετε να παίζετε με την Python, πρέπει να ανοίξετε μια *γραμμή εντολών* στον υπολογιστή σας. Πρέπει ήδη να ξέρετε πως το κάνουμε αυτό. Το μάθαμε στο κεφάλαιο [Εισαγωγή στη γραμμή εντολών](../intro_to_command_line/README.md). + +Μόλις είστε έτοιμοι, ακολουθήστε τις παρακάτω οδηγίες. + +Θέλουμε να ανοίξουμε μια κονσόλα Python. Πληκτρολογήστε `python` αν είστε σε Windows ή `python3` αν είστε σε Mac OS/Linux και πατήστε `enter`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Η πρώτη σας Python εντολή! + +Αφού εκτελέσετε την εντολή Python, το prompt θα αλλάξει σε `>>>`. Για εμάς αυτό σημαίνει ότι τώρα μπορεί να χρησιμοποιούμε μόνο εντολές για τη γλώσσα Python. Δεν χρειάζεται να πληκτρολογήσετε `>>>`. Θα το κάνει η Python για σας. + +Εάν θέλετε να τερματίσετε την κονσόλα Python σε οποιοδήποτε σημείο, απλά πληκτρολόγηστε `exit()` ή `Ctrl + Z` για Windows και `Ctrl + D` για Mac/Linux. Τότε δεν θα μπορείτε να δείτε το `>>>` πια. + +Για τώρα δεν θέλουμε να φύγουμε από αυτό το περιβάλλον. Θέλουμε να μάθουμε περισσότερα γι'αυτό. Ας ξεκινήσουμε να γράφουμε μερικές μαθηματικές πράξεις, όπως `2 + 3` και μετά πατάμε `enter`. + +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +Ωραία! Είδατε την απάντηση από κάτω; Η Python ξέρει μαθηματικά! Μπορείτε να δοκιμάσετε και άλλες εντολές, όπως: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +Για να εκτελέσετε εκθετικούς υπολογισμούς, πχ 2 στη δύναμη του 3, γράφουμε: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +Διασκέδασε με αυτό για λίγο και στη συνέχεια συνεχίστε πίσω εδώ. :) + +Όπως μπορείτε να δείτε, η Python είναι μια πολύ καλή αριθμομηχανή. Αν αναρωτιέστε τι άλλο μπορείτε να κάνετε… + +## Strings + +Τι θα λέγατε για το όνομα σας; Πληκτρολογήστε το μικρό σας όνομα μέσα σε "αυτάκια", όπως παρακάτω: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" +"Ola" +``` + +Μόλις δημιουργήσατε το πρώτο σας string! Είναι μια ακολουθία χαρακτήρων η οποία επεξεργάζεται από τον υπολογιστή. Ένα string πρέπει πάντα να ξεκινά και να τελειώνει με τον ίδιο χαρακτήρα. Αυτό μπορεί να είναι είτε μονά "αυτάκια" (`'`) ή διπλά (`"`) (καμία διαφορά!). Τα "αυτάκια" λένε στην Python το εξής: ότι υπάρχει ανάμεσα θεώρησε το ως ένα string. + +Τα strings μπορούν να ενωθούν. Δοκιμάστε το ακόλουθο: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +"Hi there Ola" +``` + +Μπορείτε επίσης να πολλαπλασιάσετε strings με αριθμό: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +Αν χρειαστεί να βάλετε κάποια απόστροφο μέσα στο string, υπάρχουν δύο τρόποι να το κάνετε. + +Χρησιμοποιώντας διπλά "αυτάκια": + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +ή κάνοντας escape την απόστροφο με ένα backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Ωραίο εε; Για να δείτε το όνομα σας σε κεφαλαία, γράψτε: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +Μόλις χρησιμοποιήσατε την `upper` **method** πάνω στο string σας! Η μέθοδος (όπως η `upper()`) είναι μια ακολουθία από οδηγίες/εντολές που η Python πρέπει να εκτελέσει πάνω σε ένα συγκεκριμένο object (`"Ola"`) μόλις την καλέσετε. + +Αν θέλετε να μάθετε τον αριθμό των γραμμάτων που περιέχονται στο όνομα σας, υπάρχει συνάρτηση **function** και γι'αυτό! + +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +Αναρρωτιέστε γιατί μερικές φορές καλείτε συναρτήσεις με την τελεία `.` στο τέλος ενός string (όπως `"Ola".upper()`) και άλλες καλείτε μια συνάρτηση και τοποθετείτε μέσα στις παρενθέσεις το string; Λοιπόν, σε κάποια σημεία οι συναρτήσεις ανήκουν σε objects, όπως η `upper()` η οποία επιδρά μόνο πάνω σε strings. Σε αυτή την περίπτωση, ονομάζουμε τις συναρτήσεις αυτές μεθόδους (**method**). Άλλες, πάλι, φορές οι συναρτήσεις δεν ανήκουν σε κάτι συγκεκριμένο και μπορούν να χρησιμοποιηθούν σε οποιουδήποτε τύπου object, όπως η `len()`. Γι'αυτό δίνουμε το string `"Ola"` ως παράμετρο στη συνάρτηση `len`. + +### Περίληψη + +Αρκετά με τα strings. Μέχρι τώρα μάθατε: + +- **το prompt** – γράφοντας εντολές (κώδικα) μέσα σε περειβάλλον της Python έχει ως αποτέλεσμα να παίρνετε απαντήσεις από την Python +- **αριθμούς και strings** – στην Python οι αριθμοί χρησιμοποιούνται για μαθηματικά και τα strings για χαρακτήρες +- **operators** – όπως `+` και `*`, συνδυάζουν τιμές και παράγουν μια νέα τιμή +- **functions** – όπως η `upper()` και η `len()`, εκτελούν κάποιες ενέργειες στα objects. + +Αυτά είναι τα βασικά για κάθε γλώσσα προγραμματισμού. Είστε έτοιμοι για κάτι πιο δύσκολο; Είμαστε σίγουροι ότι είστε! + +## Σφάλματα + +Ας δοκιμάσουμε κάτι καινούργιο. Μπορούμε να βρούμε το μήκος ενός αριθμού ακριβώς όπως κάναμε με το όνομα σας νωρίτερα; Πληκτρολογήστε `len(304023)` και πατήστε `enter`: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +Μόλις λάβατε το πρώτο σας σφάλμα! Το εικονίδιο {{ warning_icon }} είναι ο δικός μας τρόπος να σας πούμε ότι ο κώδικάς που πρόκειται να τρέξετε δεν θα έχει τα αναμενόμενα αποτελέσματα. Κάνοντας λάθη (ακόμα και εσκεμμένα) είναι σημαντικό κομμάτι κατά τη διάρκεια της εκμάθησης! + +Το συγκεκριμένο σφάλμα λέει ότι τα objects τύπου "int" (από τη λέξη integers, που σημαίνει ακέραιοι αριθμοί) δεν έχουν μήκος. Οπότε τι κάνουμε τώρα; Μήπως να γράψουμε τον αριθμό ως ένα string; Τα strings έχουν μήκος, έτσι; + +{% filename %}command-line{% endfilename %} + +```python +>>> len(str(304023)) +6 +``` + +Δούλεψε! Χρησιμοποιήσαμε τη συνάρτηση `str` μέσα στην `len`. Η `str()` μετατρέπει τα πάντα σε strings. + +- Η συνάρτηση `str` μετατρέπει πράγματα σε **strings** +- Η συνάρτηση `int` μετατρέπει πράγματα σε **integers** + +> Σημαντικό: μπορούμε να μετατρέψουμε αριθμούς σε κείμενο (strings) αλλά όχι απαραίτητα το αντίστροφο. Τι θα συνέβαινε αν τρέχατε `int('hello')`; + +## Μεταβλητές + +Ένα σημαντικό έννοια στον προγραμματισμό είναι οι μεταβλητές. Μια μεταβλητή δεν είναι τίποτε άλλο από ένα όνομα που μπορεί να επαναχρησιμοποιηθεί αργότερα. Οι προγραμματιστές χρησιμοποιούν τις μεταβλητές για την αποθήκευση δεδομένων, κάνοντας τον κώδικα πιο ευανάγνωστο χωρίς να χρειάζεται να θυμούνται τι ήταν τι. + +Ας υποθέσουμε ότι θέλετε να δημιουργήσετε μια μεταβλητή με το όνομα `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +Γράφουμε name ίσον με Ola. + +Όπως θα παρατηρήσατε, το πρόγραμμα δεν επέστρεψε τίποτα όπως πριν. Πως ξέρουμε, λοιπόν, ότι η μεταβλητή υπάρχει; Πληκτρολογήστε`name` και μετά πιέστε `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Ναιιι! Η πρώτη σας μεταβλητή! :) Μπορείτε πάντα να αλλάξετε την τιμή αυτής της μεταβλητής: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +Μπορείτε να χρησιμοποιήσετε μεταβλητές σε συναρτήσεις: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Φοβερό, έτσι; Οι μεταβλητές μπορεί να είναι οτιδήποτε (ακόμα και αριθμοί). Δοκιμάστε το εξής: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +Αλλά τι θα γινόταν αν χρησιμοποιούσαμε λάθος όνομα; Τι θα συμβεί; Ας το δοκιμάσουμε! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +Ένα σφάλμα! Όπως μπορείτε να δείτε, η Python έχει διαφορετικού τύπου σφάλματα (τα έχει κατατάξει σε κατηγορίες). Αυτό εδώ ονομάζεται **NameError**. Η Python θα σας εμφανίσει αυτό το σφάλμα αν προσπαθήσετε να χρησιμοποιήσετε κάποια μεταβλητή της οποίας το όνομα δεν έχει δηλωθεί. Αν εμφανίστηκε αυτό το σφάλμα νωρίτερα σε εσάς, δείτε τον κώδικά σας μήπως και έχετε κάνει λάθος σε κάποιο όνομα μεταβλητής. + +Παίξτε για λίγο με αυτό και δείτε τι μπορείτε να κάνετε! + +## Η συνάρτηση print + +Δοκιμάστε αυτό: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` + +Όταν απλώς πληκτρολογείτε `name`, η Python ανταποκρίνεται με το λεγόμενο string *representation* της τιμής της μεταβλητής 'name', η οποία είναι τα γράμματα M-a-r-i-a, περικυκλωμένα με τα μονά "αυτάκια", ''. Όταν λέτε `print(name)`, η Python θα "εκτυπώσει στην οθόνη" τα περιεχόμενα της μεταβλητής, χωρίς τα "αυτάκια", κάτι το οποίο είναι πιο ωραίο. + +Όπως θα δούμε και αργότερα, η συνάρτηση `print()` είναι χρήσιμη όταν θέλουμε να εκτυπώσουμε πράγματα μέσα σε συναρτήσεις ή όταν θέλουμε να εκτυπώσουμε πράγματα σε πολλαπλές γραμμές αντί μιας. + +## Λίστες + +Πέρα από τα strings και τους αριθμούς, η Python προσφέρει αρκετά ακόμα διαφορετικούς τύπους objects. Παρακάωτ θα περιγράψουμε αυτό που αποκαλούμε λίστα (**list**). Οι λίστες είναι αυτό που φαντάζεστε: objects τα οποία είναι λίστες άλλων objects. :) + +Πηγαίνετε και δημιουργήστε μια λίστα: + +{% filename %}command-line{% endfilename %} + +```python +>>> [] +[] +``` + +Ναι, αυτή είναι μια κενή λίστα. Όχι πολύ χρήσιμη έτσι; Ας δημιουργήσουμε μια λίστα με αριθμούς. Δεν θέλουμε να επαναλαμβανόμαστε όλη την ώρα, οπότε θα βάλουμε τη λίστα μέσα σε μια μεταβλητή: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +Τέλεια, έχουμε μια λίστα! Τι μπορούμε να κάνουμε με αυτή; Ας δούμε πόσοι αριθμοί υπάρχουν μέσα στη λίστα. Ξέρετε, μήπως, ποια συνάρτηση μπορούμε να χρησιμοποιήσουμε γι'αυτό; Το ξέρετε ήδη! + +{% filename %}command-line{% endfilename %} + +```python +>>> len(lottery) +6 +``` + +Ναι! Η συνάρτηση `len()` σας δίνει τον αριθμό των objects μέσα σε μια λίστα. Ωραίο, έτσι; Ίσως να μπορούμε να ταξινομήσουμε τους αριθμούς: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.sort() +``` + +Αυτό δεν επιστρέφει τίποτα, απλώς άλλαξε τη σειρά με την οποία εμφανίζονται οι αριθμοί στη λίστα. Ας εκτυπώσουμε τη λίστα να δούμε πως άλλαξαν τα δεδομένα της: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +Όπως βλέπετε, οι αριθμοί μέσα στη λίστα είναι πλέον ταξινομημένοι κατά αύξοντα αριθμό. Συγχαρητήρια! + +Ίσως να θέλουμε να αντιστρέψουμε αυτή τη σειρά. Ας το κάνουμε! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +Αν θέλετε να προσθέσετε κάτι στη λίστα σας, μπορείτε να το κάνετε με την ακόλουθη εντολή: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +Αν θέλετε να εμφανίσετε μόνο το πρώτο στοιχείο της λίστας, μπορείτε να το κάνετε χρησιμοποιώντας τα λεγόμενα **indexes**. Ένα index είναι ένας αριθμός ο οποίος δηλώνει σε ποιο σημείο ένα στοιχείο υπάρχει σε μια λίστα. Οι προγραμματιστές προτιμούν να ξεκινούν από το 0, οπότε το πρώτο στοιχείο θα βρίσκεται στη θέση (index) 0, το επόμενο στη θέση 1 κοκ. Δοκιμάστε αυτό: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` + +Όπως μπορείτε να δείτε, μπορείτε να έχετε πρόσβαση στα διαφορετικά στοιχεία μια λίστας γνωρίζοντας το όνομα της λίστας και τη θέση (index) του κάθε στοιχείου, δηλώνοντας το μέσα σε αγκύλες ([]). + +Για να διαγράψετε κάτι από τη λίστα, θα χρειαστεί να χρησιμοποιήσετε τα **indexes** καθώς και την μέθοδο `pop()`. Δηλαδή, θα πρέπει να ξέρετε ποιο στοιχείο να διαγράψετε. Ας δοκιμάσουμε ένα παράδειγμα. Θα διαγράψουμε το πρώτο στοιχείο της λίστας. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +Δούλεψε μια χαρά! + +Παίξτε λίγο παραπάνω: δοκιμάστε μερικές άλλες θέσεις (αριθμός μέσα στην αγκύλη) όπως 6, 7, 1000, -1, -6 ή -1000. Δείτε αν μπορείτε να προβλέψετε το αποτέλεσμα πριν πατήσετε enter. Συμφωνούν τα αποτελέσματα με την πρόβλεψη σας; + +Μπορείτε να βρείτε την λίστα με όλες διαθέσιμες μεθόδους για μια λίστα στο Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Λεξικά + +> Για τους αναγνώστες στο σπίτι: αυτή η ενότητα καλύπτεται στο βίντεο [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c). + +Ένα λεξικό (dictionary ή όπως έχει επικρατήσει, dict εν συντομία) είναι όμοιο με μια λίστα αλλά έχετε πρόσβαση στις τιμές όχι κατά θέση (index) αλλά κατά ένα κλειδί (key). Ένα κλειδί μπορεί να είναι ένα string ή ένας αριθμός. Η σύνταξη για ένα κενό λεξικό είναι: + +{% filename %}command-line{% endfilename %} + +```python +>>> {} +{} +``` + +Αυτό σηλώνει ότι μόλις δημιουργήσατε ένα κενό dict. Συγχαρητήρια! + +Τώρα, προσπαθήστε να εκτελέσετε την ακόλουθη εντολή (αντικαθιστώντας με δικά σας στοιχεία): + +{% filename %}command-line{% endfilename %} + +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` + +Με αυτή την εντολή μόλις δημιουργήσατε μια μεταβλητή με το όνομα `participant` με τρια ζευγάρια κλειδι-τιμή (key value pairs): + +- Το πρώτο κλειδί είναι το `name` το οποίο αντιστοιχεί την τιμή `'Ola'` (είναι ένα `string` object), +- Το δεύτερο κλειδί με το όνομα `country` αντιστοιχεί στην τιμή `'Poland'` (άλλο ένα `string`), +- και το τρίτο κλειδί `favorite_numbers` αντιστοιχεί στην τιμή `[7, 42, 92]` (μια λίστα `list` με τρεις αριθμούς μέσα της). + +Μπορείτε να δείτε τις τιμές κάθε κλειδιού με την ακόλουθη σύνταξη: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(participant['name']) +Ola +``` + +Βλέπετε ότι είναι όμοια με μια λίστα. Απλώς δεν χριάζεται να θυμάστε τη θέση - μόνο το όνομα. + +Τι θα συμβεί αν ζητήσουμε μια τιμή ενός κλειδιού η οποία δεν υπάρχει; Μπορείτε να μαντέψετε; Ας δοκιμάσουμε να δούμε! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` + +Είδατε, άλλο ένα σφάλμα το οποίο λέγεται **KeyError**. Η Python είναι αρκετά καλή σε αυτό. Δηλαδή στην περιγραφικότητα των σφαλμάτων της. Σας λέει ότι το κλειδί `'age'` δεν υπάρχει στο λεξικό. + +Πότε πρέπει να χρησιμοποιείτε λεξικό έναντι μιας λίστας; Αυτό είναι ένα καλό ερώτημα. Σκεφτείτε λίγο την απάντηση πριν προχωρήσετε. + +- Χρειάζεστε μια ταξινομημένη ακολουθία από στοιχεία; Η απάντηση είναι λίστα. +- Χρειάζεστε να συσχετίζετε κλειδιά ούτως ώστε να τα αναζητείτε αργότερα μόνο με το όνομα τους και όχι με τη θέση τους; Η απάντηση είναι dict. + +Τα dicts όπως και οι λίστες είναι *mutable*, που σημαίνει ότι μπορούν να αλλάξουν μετά τη δημιουργία τους. Μπορείτε να προσθέσετε ένα νέο κλειδί-τιμή στο λεξικό αφού δημιουργηθεί, όπως παρακάτω: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +Ελπίζουμε να βγάζουν νόημα όλα αυτά μέχρι τώρα. :) Είστε έτοιμοι για περισσότερη διασκέδαση με τα λεξικά; Συνεχίστε να διαβάζετε για περισσότερα πράγματα που μπορείτε να κάνετε. + +Μπορείτε να χρησιμοποιήσετε την μέθοδο `pop()` για να διαγράψετε ένα στοιχείο (ζευγάρι από κλειδί-τιμή) από ένα dict. Για παράδειγμα, αν θέλετε να διαγράψετε το ζευγάρι με το κλειδί `'favorite_numbers'`, γράψτε την ακόλουθη εντολή: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Όπως μπορείτε να δείτε από την έξοδο, το ζευγάρι του κλειδιού 'favorite_numbers' διαγράφηκε επιτυχώς. + +Επίσης, μπορείτε να αλλάξετε την τιμή σε μια τιμή μέσα σε ένα λεξικό (αλλά όχι το ίδιο το κλειδί). Δοκιμάστε το εξής: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Όπως βλέπετε, η τιμή του κλειδιού `'country'` αλλάξε από `'Poland'` σε `'Germany'`. :) Φοβερό έτσι; Μπράβο! Μόλις μάθατε άλλο ένα απίθανο πράγμα. + +### Περίληψη + +Τέλεια! Ξέρετε πολλά σχετικά με τον προγραμματισμό τώρα. Στην τελευταία ενότητα μάθατε τα εξής: + +- **errors** – μάθατε πως να διαβάζετε και να καταλαβαινέτε τα σφάλματα τα οποία εμφανίζονται αν η Python δεν καταλαβαίνει κάποια εντολή που της δώσατε +- **variables** – ονόματα για objects τα οποία σας επιτρέπουν να γράφετε κώδικα πιο εύκολα αλλά και να είναι ο κώδικας σας πιο ευανάγνωστος +- **lists** – λίστες από objects που αποθηκεύονται σε μια συγκεκριμένη σειρά +- **dictionaries** – αντικείμενα τα οποία αποθηκεύονται υπό τη μορφή ζευγαριού κλειδί-τιμή + +Ενθουσιασμένοι για το επόμενο μέρος; :) + +## Σύγκριση πραγμάτων + +> Για τους αναγνώστες στο σπίτι: αυτή η ενότητα καλύπτεται στο βίντεο [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4). + +Ένα μεγάλος μέρος του προγραμματισμού περιλαμβάνει τη σύγκριση πραγμάτων. Ποιο είναι το πιο εύκολο πράγμα να συγκρίνουμε; Οι αριθμοί! Ας δούμε πως: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. Nice, huh? + +Αναρρωτιέστε γιατί βάλαμε `==` (δύο ίσον σύμβολα) για να εξακριβώσουμε αν οι αριθμοί είναι ίσοι; Χρησιμοποιούμε το μονό ίσον `=` για να αναθέσουμε μια τιμή σε μια μεταβλητή. Πάντα, **πάντα** θα χρειάζεται να βάζετε διπλό ίσον – `==` – αν θέλετε να δείτε αν δύο πράγματα είναι ίσα μεταξύ τους. Αν οι τιμές τους, δηλαδή, είναι ίδιες. Μπορούμε επίσης να εξακριβώσουμε αν οι τιμές τους δεν είναι ίσες. Γι'αυτό χρησιμοποιούμε το σύμβολο `!=`, όπως φαίνεται παραπάνω. + +Ας δώσουμε στην Python δύο ακόμα εντολές: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +Είδαμε ότι τα σύμβολα `>` και `<`, αλλά τα ακόλουθα σύμβολα τι σημαίνουν: `>=`, `<=`; Διαβάστε τα κάπως έτσι: + +- x `>` y σημαίνει: το x είναι μεγαλύτερο το y +- x `<` y σημαίνει: το x είναι μικρότερο του y +- x `<=` y σημαίνει: το x είναι μικρότερο ή ίσο του y +- x `>=` y σημαίνει: το x είναι μεγαλύτερο ή ίσο του y + +Τέλεια! Θέλετε να δοκιμάσετε άλλο ένα; Δοκιμάστε αυτό: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 3 > 2 or 2 < 1 +True +``` + +Μπορείτε να δώσετε στην Python όσα νούμερα θέλετε προς σύγκριση και θα σας δώσει την απάντηση! Πολύ καλό, έτσι; + +- **and** – αν χρησιμοποιήσετε τον operator `and`, τότε και οι δύο συγκρίσεις θα πρέπει να είναι αληθείς (True) για να είναι όλη η εντολή True +- **and** – αν χρησιμοποιήσετε τον operator `or`, τότε αρκεί μόνο μια από τις συγκρίσεις να είναι αληθής (True) για να είναι όλη η εντολή True + +Έχετε ακούσει την έκφραση "συγκρίνω μήλα με πορτοκάλια"; Ας το δοκιμάσουμε με την Python: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and 'str' +``` + +Όπως ισχύει με την παραπάνω έκφραση στην καθομιλουμένη, έτσι και στην Python δεν είναι δυνατόν να συγκριθεί ένας αριθμός (`int`) με ένα string (`str`). Αντ' αυτού, εμφανίζεται ένα σφάλμα τύπου **TypeError** το οποίο μας λέει ότι οι δύο τύποι objects δεν μπορούν να συγκριθούν μεταξύ τους. + +## Λογικές τιμές + +Χωρίς να το θέλετε, μόλις μάθατε έναν νέο τύπο object στην Python. Ονομάζεται **Boolean**. + +Υπάρχουν μόνο δύο ειδών Boolean objects: + +- True +- False + +Αλλά για να το καταλάβει η Python θα πρέπει πάντα να το γράφετε ως 'True' (το πρώτο γράμμα κεφαλαίο με τα υπόλοιπα πεζά). Τα **true, TRUE, και tRUE δεν θα δουλέψουν – μόνο το True είναι σωστό.** (Το ίδιο ισχύει και για το 'False'.) + +Τα booleans μπορούν να είναι και μεταβλητές! Δείτε εδώ: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +Μπορείτε να το κάνετε και έτσι: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Εξασκηθείτε και διασκεδάστε με τα Booleans δοκιμάζοντας τις ακόλουθες εντολές: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Συγχαρητήρια! Τα Booleans είναι ένα από τα πιο διασκεδαστικά πράγματα στον προγραμματισμό και μόλις μάθατε πως να τα χρησιμοποιείτε! + +# Αποθήκευση! + +> Για τους αναγνώστες στο σπίτι: αυτή η ενότητα καλύπτεται στο βίντεο [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk). + +Τόση ώρα γράφαμε τον κώδικα στην κονσόλα η οποία μας περιορίζει στο να εισάγουμε μια γραμμή κάθε φορά. Τα περισσότερα προγράμματα αποθηκεύονται σε αρχεία και τρέχουν όταν τους ζητηθεί από τον **interpreter** ή τον **compiler** της αντίστοιχης γλώσσας προγραμματισμού. Τόση ώρα τρέχαμε τα προγράμματα μας σε μια γραμμή κάθε φορά μέσα στον Python **interpreter**. Θα χρειαστούμς περισσότερες από μια γραμμές κώδικα για τα επόμενα στάδια. Οπότε θα χρειαστεί εν συντομία να κάνουμε τα εξής: + +- Να φύγουμε από τον Python interpreter +- Να ανοίξουμε τον επεξεργαστή κώδικα της αρέσκειας μας +- Να αποθηκεύσουμε κάποιο κομμάτι κώδικα σε ένα python αρχείο (με την κατάληξη .py) +- Να το τρέξουμε! + +Για να φύγουμε από τον Python interpreter θα γράψουμε `exit()` + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` + +Αυτό θα σας επαναφέρει στη γραμμή εντολών. + +Νωρίτερα, επιλέξαμε έναν επεξεργαστή κώδικα από την ενότητα [επεξεργαστής κώδικα](../code_editor/README.md). Θα χρειαστεί να ανοίξουμε τον επεξεργαστή κώδικα και να γράψουμε κώδικα σε ένα νέο αρχείο (ή αν χρησιμοποιείτε Chromebook, δημιουργήστε ένα νέο αρχείο μέσω του Cloud IDE και ανοίξτε το αρχείο): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +Προφανώς, είστε ένας αρκετά έμπειρος Python developer τώρα, οπότε γράφτε κάποιον κώδικα μέσα στο αρχείο. + +Τώρα θέλουμε να αποθηκεύσουμε το αρχείο και να του δώσουμε ένα περιγραφικό όνομα. Ας το ονομάσουμς **python_intro.py** και ας το αποθηκεύσουμε στην επιφάνεια εργασίας. Μπορούμε να ονομάσουμε το αρχείο όπως θέλουμε αλλά το σημαντικό εδώ είναι η κατάληξηξ **.py** που πρέπει να έχει. Η κατάληξη **.py** λέει στο λειτουργικό μας σύστημα ότι αυτό το αρχείο αποτελεί ένα **εκτελέσιμο Python αρχείο** και έτσι η Python μπορεί να το τρέξει. + +> **Σημείωση** Θα πρέπει να είδατε ήδη ένα από τα πιο ωραία πράγματα στους επεξεργαστές κώδικα: τα χρώματα! Στην Python κονσόλα, όλα ήταν το ίδιο χρώμα. Τώρα βλέπετε ότι η συνάρτηση `print` έχει διαφορετικό χρώμα από ένα string. Αυτό ονομάζεται "syntax highlighting" και είναι ένα πολύ χρήσιμο χαρακτηριστικό καθώς προγραμματίζετε. Τα χρώματα θα σας δίνουν βοήθεια, όπως ένα string που του λείπει ένα "αυτάκι" ή ένα τυπογραφικό λάθος (typo) σε κάποια λέξε κλειδί της Python όπως `def` κλπ). Αυτός είναι ένας λόγος που χρησιμοποιούμε έναν επεξεργαστή κώδικα. :) :) + +Με αποθηκευμένο το αρχείο, είναι ώρα να το τρέξουμε! Χρησιμοποιώντας τις δεξιότητες που μάθατε στη γραμμή εντολών, χρησιμοποιήστε την κονσόλα για να **αλλάξετε φάκελο** και να μεταβείτε στην επιφάνεια εργασίας. + + + +Σε Mac, η εντολή θα μοιάζει κάπως έτσι: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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. + +### Αν όμως η συνθήκη δεν είναι 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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 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. + +### Περίληψη + +In the last few exercises you learned about: + +- **να συγκρίνετε πράγματα** – στην Python μπορείτε να συγκρίνετε πράγματα χρησιμοποιώντας `>`, `>=`, `==`, `<=`, `<` και `and`, `or` +- **Boolean** – ένας τύπος object το οποίο μπορεί να πάρει μόνο δύο τιμές: `True` ή `False` +- **Αποθήκευση αρχείων** – αποθήκευση κώδικα σε αρχεία ούτως ώστε να τρέχετε μεγαλύτερου όγκου προγράμματα. +- **if … elif … else** – αυτά τα statements σας επιτρέπουν να εκτελείτε κώδικα υπό συγκεκριμένες συνθήκες. +- **σχόλια** - γραμμές στην Python οι οποίες δεν εκτελούνται και σας επιτρέπουν να κάνετε τον κώδικα σας πιο περιγραφικό και ευανάγνωστο + +Time for the last part of this chapter! + +## Οι δικές σας συναρτήσεις! + +> Για τους αναγνώστες στο σπίτι: αυτή η ενότητα καλύπτεται στο βίντεο [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0). + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- Αν λέβετε ένα σφάλμα τύπου `NameError`, τότε ίσως γράψατε κάτι λάθος όπως το όνομα της συνάρτηση στο τέλος του αρχείου. Επιβεβαιώστε ότι το όνομα στη δήλωση της συνάρτηση `def hi():` είναι το ίδιο με το όνομα όταν την καλείτε `hi()`. +- Αν λάβατε ένα σφάλμα τύπου `IndentationError`, ελέγξτε ότι και οι γραμμές που καλούνται οι δύο συναρτήσεις `print` έχουν τον ίδιο αριθμό κενών στην αρχή: η Python απαιτεί όλος ο κώδικας μέσα στις συναρτήσεις να είναι στοιχισμένος το ίδιο. +- Αν δεν βλέπετε κάποια έξοδο τότε είτε έχετε παραλείψει να καλέσετε την συνάρτηση χρησιμοποιώντας τις παρενθέσεις `hi()` είτε το έχετε κάνει αλλά η κλήση της συνάρτησης (hi()) έχει *κενό* στην αρχή και αποτελεί μέρος του κυρίου σώματος της συνάρτησης (def hi():). + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + + +Congratulations! You just learned how to write functions! :) + +## Επαναλήψεις + +> Για τους αναγνώστες στο σπίτι: αυτή η ενότητα καλύπτεται στο βίντεο [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0). + +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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 by that we mean it includes the first value, but not the last. + +## Περίληψη + +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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/el-GR/template_extending/README.md b/el-GR/template_extending/README.md new file mode 100644 index 00000000000..16df5df6a05 --- /dev/null +++ b/el-GR/template_extending/README.md @@ -0,0 +1,151 @@ +# Επεκτείνοντας τα template + +Ένα άλλο ωραίο πράγμα που προσφέρει το Django είναι η **επέκταση των templates**. Τι σημαίνει αυτό; Αυτό σημαίνει ότι μπορείτε να χρησιμοποιείτε τα ίδια κομμάτια HTML για διαφορετικές σελίδες του διαδυκτιακού σας τόπου. + +Τα templates σας βοηθάνε στο να επαναχρησιμοποιήσετε το ίδιο τμήμα HTML (την ίδια, δηλαδή, πληροφορία) σε περισσότερα από ένα μέρη. Δεν χρειάζεται να επαναλαμβάνεται τον εαυτό σας σε κάθε αρχείο. Και αν χρειαστεί να αλλάξετε κάτι, δεν χρειάζεται να το κάνετε σε κάθε template παρά μόνο σε ένα! + +## Δημιουργία ενός βασικού (base) template + +Το base template είναι το πιο βασικό template που μπορείτε να επεκτείνετε σε κάθε σελίδα του ιστότοπού σας. + +Ας δημιουργήσουμε ένα αρχείο `base.html` μέσα στο `blog/templates/blog/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +Στη συνέχεια, άνοιξε το και να αντίγραψε τα πάντα από το αρχείο `post_list.html` στο `base.html`, όπως ακολούθως: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Στη συνέχεια στο αρχείο `base.html`, αντικαταστήστε τα περιεχόμενα των: ``(τα πάντα μεταξύ `` και ``) με αυτό: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}Ίσως παρατηρήσατε ότι αυτό αντικατέστησε τα πάντα από το `{% for post in posts %}` μέχρι το `{% endfor %}` με αυτό: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +Αλλά γιατί; Μόλις δημιουργήσατε ένα `block`! Χρησιμοποιήσατε ένα template tag με το όνομα `{% block %}` για να δημιουργήσετε μια περιοχή όπου μέσα θα εισαχθεί HTML. Η HTML θα έρθει από άλλο αρχείο template το οποίο κάνει extend (επεκτείνει) αυτό το template (`base.html`). Θα σας δείξουμε πως να το κάνετε αυτο σε λίγο. + +Αποθηκεύστε το template `base.html` και ανοίξτε το αρχείο `blog/templates/blog/post_list.html` ξανά. {% raw %}Θα χρειαστεί να διαγράψετε τα πάντα πάνω από το `{% for post in posts %}` και κάτω από το `{% endfor %}`. Όταν είστε έτοιμοι, το αρχείο θα δείχνει κάπως έτσι:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +Θέλουμε να χρησιμοποιήσουμε αυτό το κομμάτι ως μέρος του template μας για όλα τα blocks με περιεχόμενο. Ήρθε η ώρα να προσθέσουμε blocks σε αυτό το αρχείο! + +{% raw %}Πρέπει το όνομα του block να είναι το ίδιο με αυτό που δηλώσαμε στο template `base.html`. Πρέπει επίσης να συμπεριλάβουμε όλο τον κώδικα που ανήκει σε αυτά τα blocks. Για να γίνει αυτό, βάλτε τα όλα μεταξύ `{% block content %}` και `{% endblock %}`. Έτσι:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Μόνο ένα πράγμα έμεινε. Πρέπει να "συνδέσουμε" αυτά τα δύο templates μαζί. Αυτή είναι η έννοια της επέκτασης των template! Θα το κάνουμε αυτό προσθέτοντας τη λέξη-κλειδί "extends" στην αρχή του αρχείου. Κάπως έτσι: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Αυτό ήταν! Αποθηκεύστε το αρχείο και επιβεβαιώστε ότι η ιστοσελίδα σας λειτουργεί όπως πριν. :) + +> Αν λέβετε κάποιο σφάλμα όπως `TemplateDoesNotExist`, αυτό σημαίνει ότι δεν υπάρχει το αρχείο `blog/base.html` και ότι ο `server` τρέχει στην κονσόλα. Προσπαθήστε να τον σταματήσετε (πιέζοντας Ctrl + C) και επανεκκινήστε τον τρέχοντας την εντολή `python manage.py runserver`. \ No newline at end of file diff --git a/el-GR/whats_next/README.md b/el-GR/whats_next/README.md new file mode 100644 index 00000000000..f10b39463e0 --- /dev/null +++ b/el-GR/whats_next/README.md @@ -0,0 +1,43 @@ +# Τι υπάρχει μετά; + +Επιβράβευσε τον εαυτό σου! **Είσαι φοβερή**. Είμαστε περήφανοι! <3 + +### Τι μπορείς να κάνεις τώρα; + +Κάνε ένα διάλλειμα και χαλάρωσε! Μόλις έφερες εις πέρας κάτι πραγματικά μεγάλο. + +Μετά, ακολούθησε την κοινότητα Django Girls στο [Facebook](http://facebook.com/djangogirls) ή/και στο [Twitter](https://twitter.com/djangogirls) ούτως ώστε να μένεις ενημερωμένος. + +### Μπορείς να προτείνεις τυχόν επιπρόσθετες πηγές; + +Ναι! Υπάρχουν *πολλές* πηγές στο διαδίκτυο σχετικά με την εκμάθηση γλωσσών προγραμματισμού όλων των ειδών. Ίσως να είναι δύσκολη η επιλογή του επόμενου βήματος αλλά μην ανησυχείτε. Σας καλύπτουμε. Όποια και αν ήταν τα ενδιαφέροντα σας προτού έρθετε στην κοινότητα των Django Girls και οποιαδήποτε ενδιαφέροντα αναπτύξατε κατά τη διάρκεια του οδηγού, παρακάτω σας παρουσιάζουμε μερικές δωρεάν πηγές (κάποιες από τις οποίες δεν είναι αμιγώς δωρεάν αλλά περιέχουν δωρεάν κομμάτια) τις οποίες μπορείτε να χρησιμοποιήσετε προκειμένου να πετύχετε τον στόχο σας. + +#### Django + +- Το άλλο μας βιβλίο, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Ο επίσημος οδηγός του Django](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Ξεκινώντας με το Django με μαθήματα βίντεο](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS και JavaScript + +- [Μάθημα web development από την εταιρεία Codecademy](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Μάθημα Python από την εταιρεία Codecademy](https://www.codecademy.com/learn/learn-python) +- [Μάθημα Python από την Google](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – οι πρώτες ασκήσεις είναι δωρεάν +- [New Coder tutorials](http://newcoder.io/tutorials/) – είναι μια ποικιλία πρακτικών παραδειγμάτων του πως μπορεί να χρησιμοποιηθεί η γλώσσα προγραμματισμού Python +- [edX](https://www.edx.org/course?search_query=python) – σε αυτό το γνωστό site, μπορείτε να παρακολουθήσετε τα περισσότερα μαθήματα δωρεάν αλλά για την απόκτηση κάποιου πιστοποιητικού τότε θα χρειαστεί να καταβάλετε κάποιο ποσό ανάλογα το μάθημα και το πιστοποιτικό +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Δουλεύοντας με δεδομένα + +- [Μάθημα επιστημονικών δεδομένων από την εταιρία Codecademy](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – σε αυτό το γνωστό site, μπορείτε να παρακολουθήσετε τα περισσότερα μαθήματα δωρεάν αλλά για την απόκτηση κάποιου πιστοποιητικού τότε θα χρειαστεί να καταβάλετε κάποιο ποσό ανάλογα το μάθημα και το πιστοποιτικό +- [Dataquest](https://www.dataquest.io/) – οι πρώτες 30 "αποστολές" είναι δωρεάν + +Ανυπομονούμε να δούμε το επόμενο σας project! \ No newline at end of file diff --git a/el/GLOSSARY.md b/el/GLOSSARY.md new file mode 100644 index 00000000000..c055917f508 --- /dev/null +++ b/el/GLOSSARY.md @@ -0,0 +1,3 @@ +# Επεξεργαστής Κώδικα + +Ο επεξεργαστής κώδικα είναι μια εφαρμογή που σου επιτρέπει να αποθηκεύσεις τον κώδικα σου, ώστε να είσαι σε θέση να επιστρέψεις σε αυτό αργότερα. Μπορείς να μάθεις πού μπορείς να βρείς ένα από το [κεφάλαιο επεξεργαστής κώδικα](./code_editor/README.md) \ No newline at end of file diff --git a/el/README.md b/el/README.md new file mode 100644 index 00000000000..08a1731aa9f --- /dev/null +++ b/el/README.md @@ -0,0 +1,51 @@ +# Φροντιστήριο Django Girls + +[![Γκλιτερ](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/ + +## Καλώς ήρθατε + +Καλώς ήρθατε στο φροντιστήριο Django Girls! Χαιρόμαστε που σε βλέπουμε εδώ :) Σε αυτό το σεμινάριο, θα σε πάμε ένα ταξίδι κάτω από την κουκούλα των τεχνολογιών ιστοσελίδων. προσφέροντας σου μία γεύση από όλα τα κομμάτια που πρέπει να συγκεντρωθούν ώστε να κάνουν τον ιστό να δουλέψει όπως το γνωρίζουμε. + +Όπως με όλα τα άγνωστα πράγματα, αυτό πρόκειται είναι μία εμπειρία- αλλά μην ανησυχείς, αφού ήδη πήρες την απόφαση να είσαι εδώ, θα είσαι μια χαρά :) + +## Εισαγωγή + +Έχεις νιώσει ποτέ ότι ο κόσμος γίνεται όλο και περισσότερο σχετικός με την τεχνολογία και δεν μπορείς (ακόμα) να σχετιθείς; Έχεις ποτέ αναρωτηθεί πώς να δημιουργήσεις μια ιστοσελίδα, αλλά ποτέ δεν είχες αρκετό κίνητρο για να ξεκινήσεις; Έχεις ποτέ σκεφτεί οτι ο κόσμος του software είναι πολύ περίπλοκος για σένα για να προσπαθήσεις να κάνεις κάτι από μόνη σου; + +Λοιπόν, έχουμε καλά νέα για 'σένα! Ο προγραμματισμός δεν είναι τόσο δύσκολος όσο φαίνεται, και θέλουμε να σου δείξουμε πόσο διασκεδαστικός μπορεί να είναι. + +Αυτό το σεμινάριο δεν θα σε μετατρέψει σε προγραμματιστή ως δια μαγείας. Αν θέλεις να γίνεις καλή προγραμματίστρια, χρειάζεται μήνες ή ακόμη και χρόνια εκμάθησης και πρακτικής εξάσκησης. Όμως θέλουμε να σου δείξουμε οτι ο προγραμματισμός ή η δημιουργία ιστιοσελίδων δεν είναι τόσο περίπλοκο όσο φαίνεται. Θα προσπαθήσουμε να σου εξηγήσουμε τα διάφορα κομμάτια όσο καλύτερα μπορούμε, ούτως ώστε να μην σε φοβίζει η τεχνολογία. + +Ελπίζουμε να μπορέσουμε να σε κάνουμε να αγαπήσεις την τεχνολογία, όπως εμείς! + +## Τι θα μάθεις κατα τη διάρκεια του tutorial; + +Μόλις τελειώσετε το σεμινάριο, θα έχετε μία μικρή λειτουργική εφαρμογή ιστού: το δικό σας blog. Θα σας δείξουμε πως να το ανεβάσετε ηλεκτρονικά, ώστε άλλοι να δουν την δουλειά σας! + +Θα φαίνεται έτσι (πάνω κάτω): + +![Σχήμα 0.1](images/application.png) + +> Αν δουλεύεις με το σεμινάριο μόνος σου και δεν έχεις κάποιον προπονητή που θα σε βοηθήσει σε περίπτωση ενός προβλήματος, έχουμε ένα σύστημα συνομιλίας για εσένα:[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). Ζητήσαμε από τους προπονητές μας και τους προηγούμενους συμμετάσχοντες να είναι εκεί που και που και να βοηθάνε άλλους με το σεμινάριο! Μην φοβάστε να κάνετε ερωτήσεις εκεί! + +Οκ,[ ας ξεκινήσουμε από την αρχή....](./how_the_internet_works/README.md) + +## Ακολουθώντας το φροντιστήριο στο σπίτι + +Είναι εκπληκτικό να λάβετε μέρος στο εργαστήρι Django Girls, αλλά γνωρίζουμε ότι δεν είναι πάντα δυνατό να παρακολουθήσετε ένα. Για αυτό σας ενθαρρύνουμε να προσπαθήσετε να ακολουθήσετε αυτό το σεμινάριο στο σπίτι. Για τους αναγνώστες στο σπίτι, προς το παρόν ετοιμάζουμε βίντεο που θα το κάνουν ευκολότερο να παρακολουθήσετε το σεμινάριο από μόνοι σας. Είναι ακόμα έργο σε εξέλιξη, αλλά όλο και περισσότερα πράγματα θα καλυφθούν σύντομα στο [ ](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) κανάλι του YouTube. + +Σε κάθε κεφάλαιο που έχει ήδη καλυφθεί, υπάρχει ένας σύνδεσμος που οδηγεί στο σωστό βίντεο. + +## Σχετικά και συμβάλλοντας + +Αυτό το σεμινάριο συντηρείται από [DjangoGirls](https://djangogirls.org/). Εάν βρείτε τυχόν λάθη η θέλετε να ενημερώσετε το φροντιστήριο παρακαλούμε [ ακολουθήστε τις οδηγίες για συμβολή](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## Θα θέλατε να μας βοηθήσετε να μεταφράσετε το σεμινάριο σε άλλες γλώσσες; + +Προς το παρόν, οι μεταφράσεις διατηρούνται στην πλατφόρμα του crowdin.com στο: + +https://crowdin.com/project/django-girls-tutorial + +Εάν η γλώσσα σας δεν είναι καταχωρημένη στο [crowdin](https://crowdin.com/), παρακαλούμε [ ανοίξτε ένα νέο θέμα](https://github.com/DjangoGirls/tutorial/issues/new) ενημερώνοντας μας για την γλώσσα ώστε να την προσθέσουμε. \ No newline at end of file diff --git a/el/SUMMARY.md b/el/SUMMARY.md new file mode 100644 index 00000000000..afeababe25c --- /dev/null +++ b/el/SUMMARY.md @@ -0,0 +1,27 @@ +# Περίληψη + +* [Εισαγωγή](README.md) +* [Εγκατάσταση](installation/README.md) +* [Εγκατάσταση (chromebook)](chromebook_setup/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) +* [Μοντέλα (models) του Django](django_models/README.md) +* [Διαχείριση μέσω Django admin](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](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) \ No newline at end of file diff --git a/el/chromebook_setup/README.md b/el/chromebook_setup/README.md new file mode 100644 index 00000000000..322e9ede763 --- /dev/null +++ b/el/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Εγκατάσταση του Chromebook + +> **Σημείωση** Εάν έχετε ήδη τελειώσει με τα βήματα της εγκατάστασης, δεν χρειάζεται να επαναλάβετε αυτή την ενότητα - μπορείτε να πάτε απευθείας στην ενότητα [ Εισαγωγή στην Python](../python_introduction/README.md). + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/el/chromebook_setup/instructions.md b/el/chromebook_setup/instructions.md new file mode 100644 index 00000000000..f031097fb2b --- /dev/null +++ b/el/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +Μπορείτε [ να παραλείψετε αυτή την ενότητα](http://tutorial.djangogirls.org/en/installation/#install-python) εάν δεν χρησιμοποιείτε το Chromebook. Εάν το χρησιμοποιείτε, η διαδικασία εγκατάστασης θα είναι λίγο διαφορετική. Σε αυτή την περίπτωση μπορείτε να αγνοήσετε τις υπόλοιπες οδηγίες εγκατάστασης. + +### 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 the software. Για τη διάρκεια του workshop, το Cloud 9 θα είναι *το τοπικό σας μηχάνημα*. Με αυτόν τον τρόπο θα μπορείτε να τρέχετε εντολές σε ένα τερματικό περιβάλλον ακριβώς όπως και οι συμμαθητές σας με OS X, Ubuntu ή Windows, αλλά το δικό σας τερματικό θα είναι συνδεδεμένο με έναν υπολογιστή που τρέχει σε server του Cloud 9. + +1. Εγκαταστήστε το Cloud 9 από το [ web store του Chrome](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Πηγαίντε στο [c9.io](https://c9.io) +3. Δημιουργήστε λογαριασμό +4. Κάντε κλικ στο * Create a New Workspace* +5. Ονομάστε το *django-girls* +6. Επιλέξτε το *Βlank*(Δεύτερο από δεξιά στην κάτω γραμμή με το πορτοκαλί λογότυπο) + +Τώρα πρέπει να βλέπετε μια σελίδα με ένα μεγάλο κύριο παράθυρο με κείμενο, μία πλαϊνή μπάρα και ένα μικρό παράθυρο στο τέλος που μοιάζει κάπως έτσι: + +{% filename %}Cloud 9{% endfilename %} + + yourusername:~/workspace $ + + +This bottom area is your *terminal*, where you will give the computer Cloud 9 has prepared for your instructions. You can resize that window to make it a bit bigger. + +### Εικονικό Περιβάλλον + +Ένα εικονικό περιβάλλον( γνωστό και ως virtualenv) είναι σαν ένα ιδιωτικό κουτί που μπορούμε να χωρέσουμε χρήσιμο υπολογιστικό κώδικα για ένα πρότζεκτ στο οποίο εργαζόμαστε. Τα χρησιμοποιούμε για να κρατήσουμε διάφορα κομμάτια κώδικα που θέλουμε για τα διαφορετικά πρότζεκτ μας χωριστά ώστε τα πράγματα να μην μπερδεύονται μεταξύ τους μεταξύ πρότζεκτ. + +Εάν ο ακροδέκτης σας είναι στο κάτω μέρος της διεπαφής του Cloud 9, εκτελέστε το ακόλουθο: + +{% filename %}Cloud 9{% endfilename %} + + sudo apt update + sudo apt install python3.6-venv + + +Εάν εξακολουθεί να μην λειτουργεί, ζήτησε βοήθεια από τον προπονητή σας. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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 + +Το φροντιστήριο Django Girls συμπεριλαμβάνει μια ενότητα στο τι αποκαλείται Ανάπτυξη, το οποίο είναι η διαδικασία όπου παίρνεις τον κώδικα που τροφοδοτεί την νέα σου εφαρμογή δικτύου και την μετακινεί σε ένα δημόσια προσιτό υπολογιστή (που ονομάζεται διακομιστής) έτσι ώστε άλλα άτομα μπορούν να δουν την εργασία σου. + +Αυτό το μέρος είναι λίγο περίεργο όταν κάνεις το φροντιστήριο σε ένα Chromebook μιας και χρησιμοποιούμε ήδη έναν υπολογιστή ο οποίος είναι στο διαδίκτυο ( σε αντίθεση, ας πούμε, με ένα φορητό υπολογιστή). 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). \ No newline at end of file diff --git a/el/code_editor/README.md b/el/code_editor/README.md new file mode 100644 index 00000000000..cba0e64763d --- /dev/null +++ b/el/code_editor/README.md @@ -0,0 +1,11 @@ +# Επεξεργαστής Κώδικα + +> Για τους αναγνώστες στο σπίτι: αυτό το κεφάλαιο καλύπτεται στο [ Εγκαθιστώντας την Python& Πρόγραμμα επεξεργασίας κώδικα](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s)βίντεο. + +Είσαι έτοιμη να γράψεις την πρώτη σου γραμμή κώδικα, οπότε ήρθε η ώρα για να κατεβάσεις ένα πρόγραμμα επεξεργασίας κώδικα (code editor)! + +> **Σημείωση** εάν χρησιμοποιείτε ένα Chromebook, πηδήξτε αυτό το κεφάλαιο και σιγουρευτείτε ότι ακολουθείτε τις οδηγίες [Εγκατάστασης Chromebook](../chromebook_setup/README.md). +> +> **Σημείωση** Μπορεί να το έχετε ήδη κάνει αυτό νωρίτερα στο κεφάλαιο εγκατάστασης- αν ναι, μπορείτε να παραλείψετε κατευθείαν στο επόμενο κεφάλαιο! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/el/code_editor/instructions.md b/el/code_editor/instructions.md new file mode 100644 index 00000000000..bdb6ca1d6cb --- /dev/null +++ b/el/code_editor/instructions.md @@ -0,0 +1,31 @@ +Υπάρχουν πολλά code editors διαθέσιμοι και για αυτό είστε ελεύθεροι να διαλέξετε αυτόν που σας αρέσει περισσότερο. Οι περισσότεροι προγραμματιστές της Python χρησιμοποιούν περίπλοκα, αλλά εξαιρετικά ισχυρά IDEs (Integrated Development Environments-Ολοκληρωμένα Περιβάλλοντα Ανάπτυξης), όπως το PyCharm. Για αρχάριους, ωστόσο, αυτή η επιλογή είναι ίσως λιγότερο κατάλληλη· οι συστάσεις μας είναι προγράμματα εξίσου ισχυρά, αλλά πολύ απλούστερα. + +Οι προτάσεις μας είναι παρακάτω, αλλά μην διστάσετε να ρωτήσετε τον προπονητή σας ποιες είναι οι προτιμήσεις του- θα είναι ευκολότερο να σας βοηθήσουν. + +## Gedit + +Το Gedit είναι ένα ανοικτού κώδικα (open source), δωρεάν πρόγραμμα επεξεργασίας (free editor), διαθέσιμο για όλα τα λειτουργικά συστήματα. + +[Κατέβασέ το εδώ](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[Κατέβασέ το εδώ](https://www.sublimetext.com/3) + +## Atom + +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. + +[Κατέβασέ το εδώ](https://atom.io/) + +## Γιατί χρειαζόμαστε τον Επεξεργαστή Κώδικα; + +Μπορεί να αναρωτιέσαι γιατί εγκαθιστούμε αυτό το ειδικό πρόγραμμα επεξεργασίας κώδικα λογισμικού, αντί να χρησιμοποιήσουμε κάτι σαν το Word ή το 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). + +Δεύτερον, τα προγράμματα επεξεργασίας κώδικα είναι εξειδικευμένα στην σύνταξη κώδικα, έτσι μπορούν να παρέχουν χρήσιμα χαρακτηριστικά όπως η επισήμανση κώδικα με χρώμα σύμφωνα με την σημασία του, η αυτόματο κλείσιμο εισαγωγικών. + +Θα τα δούμε όλα αυτά αργότερα σε δράση. Σύντομα, θα αρχίσεις να βλέπεις τον παλιό, έμπιστο επεξεργαστή σου κώδικα ως ένα από τα αγαπημένα σου εργαλεία. :) \ No newline at end of file diff --git a/el/css/README.md b/el/css/README.md new file mode 100644 index 00000000000..4f8d9fb7bf7 --- /dev/null +++ b/el/css/README.md @@ -0,0 +1,304 @@ +# CSS- κάνε το όμορφο! + +Το blog μας φαίνεται ακόμα αρκετά άσχημο, έτσι δεν είναι; Ωρα να το κάνουμε όμορφο! Γι'αυτή τη δουλειά θα χρησιμοποιούμε τη CSS. + +## Τι είναι η CSS; + +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. ;) + +Άλλα δεν θέλουμε να ξεκινήσουμε από την αρχή ξανά, έτσι; Άλλη μια φορά, θα χρησιμοποιήσουμε κάτι που οι προγραμματιστές κυκλοφόρησαν δωρεάν στο διαδίκτυο. Το να ανακαλύπτουμε τον τροχό δεν έχει πλάκα, ξέρετε. + +## Ας χρησιμοποιήσουμε το Bootstrap! + +Bootstrap is one of the most popular HTML and CSS frameworks for developing beautiful websites: https://getbootstrap.com/ + +Γράφτηκε από προγραμματιστές που εργάστηκαν στο Twitter. Τώρα αναπτύσσεται από εθελοντές από ολόκληρο το κόσμο! + +## Εγκατάσταση του Bootstrap + +Για να εγκαταστήσετε το Bootstrap, πρέπει να προσθέσετε αυτό στο `` στο `html`αρχείο σας: + +{% 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! + +![Σχήμα 14.1](images/bootstrap1.png) + +Δείχνει ήδη πολύ καλύτερο! + +## Στατικά αρχεία στο Django + +Τέλος, ας ρίξουμε μια πιο προσεκτική ματιά στα λεγόμενα **στατικά αρχεία**. 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. + +### Πού βρίσκονται τα στατικά αρχεία στο Django + +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`. + +Για να το κάνουμε αυτό πρέπει να δημιουργήσουμε ένα φάκελο με το όνομα `static` μέσα στο φάκελο του app blog: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │   └── templates + └── mysite + + +Το Django θα βρίσκει αυτόματα οποιοδήποτε φάκελο ονομάζεται "static" μέσα στους φακέλους οποιασδήποτε εφαρμογή σας. Έπειτα θα μπορεί να χρησιμοποιεί το περιεχόμενο τους ως στατικά αρχεία. + +## Το πρώτο CSS αρχείο σας! + +Ας δημιουργήσουμε ένα CSS αρχείο τώρα, για να προσθέσετε το δικό σας στυλ στην ιστοσελίδα σας. Δημιουργήστε έναν νέο κατάλογο που ονομάζεται `css` μέσα στο `static` κατάλογο. Στη συνέχεια, δημιουργήστε ένα νέο αρχείο που ονομάζεται `blog.css` μέσα σε αυτόν τον κατάλογο `css`. Είστε έτοιμη; + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +Ώρα να γράψουμε λίγη CSS! Άνοιξε το αρχείο `blog/static/css/blog.css` στον επεξεργαστή. + +We won't be going too deep into customizing and learning about CSS here. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +Αλλά ας δοκιμάσουμε μερικά πράγματα. Ίσως θα μπορούσαμε να αλλάξουμε το χρώμα του τίτλου της σελίδας μας; Για να καταλάβουν τα χρώματα, οι υπολογιστές χρησιμοποιούν ειδικούς κώδικες. Αυτοί οι κώδικες ξεκινάνε με `` και ακολουθούνται από 6 γράμματα (A-F) και αριθμούς (0-9). Για παράδειγμα, ο κωδικός για το μπλε είναι `#0000FF`. Μπορείτε να βρείτε τους κωδικούς των χρωμάτων για πολλά χρώματα εδώ: http://www.colorpicker.com/. Context | Request Context. Μπορείς επίσης να χρησιμοποιήσεις [προκαθορισμένα χρώματα](http://www.w3schools.com/colors/colors_names.asp) με το αγγλικό όνομά τους, όπως το `red` (κόκκινο) και το `green` (πράσινο. + +Στο αρχείο `blog/static/css/blog.css` πρέπει να προσθέσεις τον παρακάτω κώδικα: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a { + color: #FCA205; +} +``` + +Το `h1 a` είναι ένας επιλογέας CSS. This means we're applying our styles to any `a` element inside of an `h1` element. Έτσι όταν έχουμε κάτι σαν `

σύνδεσμο

`, το `h1 a ` στυλ θα εφαρμοστεί. Σε αυτή τη περίπτωση, του λέμε να αλλάξει το χρώμα του σε `#FCA205`, που είναι πορτοκαλί. Φυσικά μπορείς να βάλεις το δικό σου χρώμα εδώ! + +Μέσα σε ενα αρχείο CSS καθορίζουμε τα στύλ για τα στοιχεία μέσα στο HTML αρχείο. Ο πρώτος τρόπος που αναγνωρίζουμε στοιχεία είναι με το όνομα στοιχείου. Μπορεί να τα θυμάστε αυτά ως ετικέτες από το τμήμα HTML. 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) και η ταυτότητα (id) είναι ονόματα που δίνεις εσύ στο κάθε στοιχείο. Οι τάξεις αναφέρονται σε ομάδες στοιχείων και οι ταυτότητες σε συγκεκριμένα στοιχεία. 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 + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +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. :) Between the `` and `` tags, after the links to the Bootstrap CSS files, add this line: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Ο browser διαβάζει τα αρχεία με την σειρά που δίνονται, οπότε πρέπει να σιγουρευτούμε ότι αυτή είναι η σωστή θέση. Διαφορετικά ο κωδικός στο αρχείο μας μπορεί να παρακαμφθεί από τον κώδικα στα αρχεία Bootstrap. Είπαμε στο template μας που βρίσκεται το CSS αρχείο μας. + +Το αρχείο σου πρέπει τώρα να μοιάζει κάπως έτσι: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +Εντάξει, αποθηκεύσε το αρχείο και να ανανεώσε την σελίδα! + +![Σχήμα 14.2](images/color2.png) + +Πολύ καλά! Ίσως να θέλουμε να δώσουμε λίγο αέρα στην ιστιοσελίδα μας και να αυξήσουμε το περιθώριο στα αριστερά; Ας το δοκιμάσουμε! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +Προσθέστε αυτό στο CSS σας, αποθηκεύστε τον φάκελο και δείτε πως λειτουργεί! + +![Σχήμα 14.3](images/margin2.png) + +'Ισως μπορούμε να αλλάξουμε την γραμματοσειρά της επικεφαλίδας μας. Μεσα στο `` που βρίσκεται μεσα στο αρχείο `blog/templates/blog/post_list.html` βάλε αυτό: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +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). + +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; + font-family: 'Lobster'; +} +``` + +![Σχήμα 14.3](images/font.png) + +Τέλεια! + +Όπως αναφέρθηκε παραπάνω, CSS έχει μια έννοια των τάξεων. Αυτά σας επιτρέπουν να ονομάσετε ένα μέρος του κώδικα HTML και να εφαρμόσετε στυλ μόνο σε αυτό το μέρος, χωρίς να επηρεάσετε άλλα μέρη. Αυτό μπορεί να είναι εξαιρετικά χρήσιμο! Maybe you have two divs that are doing something different (like your header and your post). Μια κατηγορία μπορεί να σε βοηθήσει να τα κάνετε να μοιάζουν διαφορετικά. + +Ονόμασε μερικά μέρη του HTML. Πρόσθεσε μια τάξη που ονομάζεται `page-header` στο `div` που περιέχει την επικεφαλίδα σου, έτσι: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Και τώρα να προσθέσετε μια τάξη `post` στο `div` που περιέχει ένα blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Τώρα θα προσθέσουμε κώδικα σε διάφορους επιλογείς (selectors). Οι επιλογείς που ξεκινούν με `.` αναφέρονται σε τάξεις. Υπάρχουν πολλά σπουδαία σεμινάρια και εξηγήσεις σχετικά με την CSS στο δίκτυο τα οποία θα σε βοηθήσουν να καταλάβεις τον παρακάτω κώδικα. Προς το παρών, απλά αντίγραψε τα παρακάτω στο αρχείο `blog/static/css/blog.css`: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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 των posts. Αντικατάστησε αυτό: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +μέσα στο αρχείο `blog/templates/blog/post_list.html` με αυτό: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Αποθήκευσε τα αρχεία και ανανέωσε την ιστοσελίδα σου. + +![Σχήμα 14.4](images/final.png) + +Woohoo! Φαίνεται τέλειο, έτσι δεν είναι; Κοιτάξτε στον κωδικό που μόλις κάναμε επικόλληση για να βρείτε τα σημεία που προσθέσαμε τάξεις στο HTML και τα χρησιμοποιήσαμε στο CSS. Που θα κάνατε την αλλαγή αν θέλατε την ημερομηνία να είναι τιρκουάζ; + +Μην φοβάστε να πειραματιστείτε με το CSS λίγο και να προσπαθήσετε να αλλάξετε μερικά πράγματα. Παίζοντας με το CSS μπορεί να σε κάνει να καταλάβεις τι κάνουν τα διάφορα πράγματα. Εάν σπάσεις κάτι, μην ανησυχείς- μπορείς πάντα να το αναιρέσεις! + +Πραγματικά συστήνουμε να πάρετε αυτή την δωρεάν online σειρά μαθημάτων Codeacademy HTML &. Μπορεί να σε βοηθήσει να μάθεις τα πάντα σχετικά με το να κάνεις τις ιστοσελίδες σου ομορφότερες με το CSS.

+ +Είσαι έτοιμη για το επόμενο κεφάλαιο; :) \ No newline at end of file diff --git a/el/deploy/README.md b/el/deploy/README.md new file mode 100644 index 00000000000..609e0972a80 --- /dev/null +++ b/el/deploy/README.md @@ -0,0 +1,255 @@ +# Ανεβάστε! + +> **Σημείωση** Το ακόλουθο κεφάλαιο μπορεί να είναι μερικές φορές λίγο δύσκολο να ολοκληρωθεί. Επιμένετε και τελειώστε το, το ανέβασμα είναι ένα σημαντικό μέρος της διαδικασίας ανάπτυξης της ιστοσελίδας. Το κεφάλαιο αυτό τοποθετείται στη μέση του εκπαιδευτικού εγγράφου, έτσι ώστε να μέντορας σας να μπορεί να σας βοηθήσει με την ελαφρώς πιο περίπλοκη διαδικασία "ανεβάσματος" της ιστοσελίδας στο διαδίκτυο. Αυτό σημαίνει ότι μπορείτε να ολοκληρώσετε την εκπαίδευση μόνοι σας ακόμα και αν σας τελειώσει ο χρόνος. + +Μέχρι τώρα, η ιστοσελίδα σου ήταν μόνο διαθέσιμη στον υπολογιστή σου. Τώρα θα μάθεις πως να την αναπτύσσεις! Ανεβάζω στο διαδίκτυο" είναι η διαδικασία της δημοσίευσης την εφαρμογής σας στο διαδίκτυο, έτσι ώστε οι άνθρωποι τελικά να πάνε και να δουν την εφαρμογή σας. :) + +Όπως μάθατε, μια ιστοσελίδα πρέπει να βρίσκεται σε ένα διακομιστή. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +Η άλλη εξωτερική υπηρεσία που θα χρησιμοποιήσουμε είναι το [GitHub](https://www.github.com), το οποίο είναι μια υπηρεσία φιλοξενίας κώδικα. Υπάρχουν και άλλοι διαθέσιμοι έξω, αλλά σχεδόν όλοι οι προγραμματιστές έχουν λογαριασμό GitHub αυτές τις μέρες, και έτσι και εσείς θα έχετε τώρα! + +Αυτά τα τρία μέρη θα είναι σημαντικά για εσάς. Ο τοπικός σας υπολογιστής θα είναι το μέρος όπου θα κάνετε ανάπτυξη και δοκιμή. Όταν είστε ικανοποιημένοι με τις αλλαγές, θα τοποθετήσετε ένα αντίγραφο του προγράμματος σας στο GitHub. Η ιστοσελίδα σας θα είναι στο PythonAnywhere και θα την ενημερώσετε με το να πάρετε ένα καινούριο αντίγραφο του κωδικού σας από το GitHub. + +# Git + +> **Σημείωση** Αν κάνατε ήδη τα βήματα εγκατάστασης, δεν χρειάζεται να τα ξανακάνετε- μπορείτε να παραλείψετε στην επόμενη ενότητα και να ξεκινήσετε να δημιουργείτε το αρχείο αποθήκευσης του Git. + +{% include "/deploy/install_git.md" %} + +## Ξεκινώντας το αρχείο αποθήκευσής μας του Git + +Το Git παρακολουθεί τις αλλαγές σε ένα συγκεκριμένο σύνολο αρχείων που αποκαλείται αρχείο αποθήκευσης κώδικα (ή «ρεπό» εν συντομία). Ας ξεκινήσουμε ένα για την εφαρμογή μας. Ανοίξτε την κονσόλα σας και να εκτελέσετε αυτές τις εντολές, στον φάκελο`djangogirls`: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. Θα πρέπει να βρίσκεστε στο φάκελο `djangogirls`. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Το όνομά σας" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Το Git θα παρακολουθείσει τις αλλαγές σε όλα τα αρχεία και τους φακέλους σε αυτόν τον κατάλογο, ωστόσο υπάρχουν ορισμένα αρχεία που θέλουμε να τα αγνοήσει. Το κάνουμε αυτό δημιουργώντας ένα αρχείο που ονομάζεται `.gitignore` στον αρχικό κατάλογο. Ανοίξτε το πρόγραμμα επεξεργασίας κειμένου και δημιουργήστε ένα νέο αρχείο με το ακόλουθο περιεχόμενο: + +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Σημείωση** Η τελεία στην αρχή του ονόματος του αρχείου είναι σημαντική! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. Αυτό το αρχείο είναι η τοπική σου βάση δεδομένων, όπου όλες οι δημοσιεύσεις σου αποθηκεύονται. Δεν θέλουμε να προσθέσουμε αυτό στην αποθήκη σας επειδή η ιστοσελίδα σας στο PythonAnywhere πρόκειται να χρησιμοποιεί διαφορετική βάση δεδομένων. Η βάση δεδομένων μπορεί να είναι SQLite, όπως η μηχανή ανάπτυξης σας, αλλά συνήθως θα χρησιμοποιείται μία που ονομάζεται MySQL η οποία μπορεί να ασχοληθεί με πολύ περισσότερους επισκέπτες από την SQLite. Έτσι και αλλιώς, αγνοώντας την βάση δεδομένων σας SQLite για την αντιγραφή στο GitHub, σημαίνει ότι όλες οι δημοσιεύσεις σας που έχετε δημιουργήσει μέχρι τώρα πρόκειται να μείνουν και να είναι διαθέσιμες τοπικά, αλλά θα πρέπει να τις προσθέσετε ξανά στην παραγωγή. Να σκέφτεστε την τοπική βάση δεδομένων σας ως ένα παιδότοπο όπου μπορείτε να δοκιμάσετε διαφορετικά πράγματα και να μην φοβάστε ότι πρόκειται να διαγράψετε τις αληθινές σας δημοσιεύσεις από το blog σας. + +Είναι καλή ιδέα να χρησιμοποιήσετε την εντολή `git status` πριν από την εντολή`git add` ή όποτε δεν είστε βέβαιοι για το τι έχει αλλάξει. Αυτό θα βοηθήσει να αποτραπούν οποιεσδήποτε εκπλήξεις, όπως το να προστεθούν ή να αποθηκευτούν λανθασμένα αρχεία. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. Τα δεδομένα εξόδου πρέπει να είναι παρόμοια με τα ακόλουθα: + +{% filename %}command-line{% endfilename %} + + 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) + + +Και τέλος σώζουμε τις αλλαγές μας. Πηγαίνετε στην κονσόλα σας και να εκτελέσετε αυτές τις εντολές: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (Αν το κάνατε ήδη στην προετοιμασία εργαστηρίου, θαυμάσια!) + + Έπειτα, δημιουργήστε ένα νέο χώρο αποθήκευσης, ονομάζοντας το "το πρώτο μου blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. Είναι πιθανώς ευκολότερο να παραμείνετε στο όνομα "το πρώτο μου blog". + + Στην επόμενη οθόνη, θα δείτε την διεύθυνση URL του κλώνου του αποθηκευτικού χώρου σας. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Πληκτρολογήστε τα ακόλουθα στην κονσόλα σας (Αντικαταστήστε '; με το όνομα χρήστη που εισάγατε όταν δημιουργήσατε τον λογαριασμό GitHub σας, αλλά χωρίς τις αγκύλες) + + {% filename %}Γραμμή εντολών{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Εισάγετε το GitHub όνομα χρήστη και κωδικό σας και θα πρέπει να δείτε κάτι σαν αυτό: + + {% filename %}γραμμή εντολών{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Πηγαίνετε και τσεκάρετέ το! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Διαλέξτε την επιλογή να ξεκινήσετε μία κονσόλα "Bash" - αυτή είναι η PythonAnywhere έκδοση της κονσόλας, όπως αυτή στον υπολογιστή σας. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Ας τραβήξουμε μας κώδικά μας από το GitHub στο PythonAnywhere, δημιουργώντας έναν «κλώνο» του αρχείου αποθήκευσής μας. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Υπομονή, υπομονή! Αλλά αν πάρει πάνω από πέντε λεπτά, κάτι είναι λάθος. Ρωτήστε τον προπονητή σας. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. Έτσι οι λογαριασμοί χρήστη και οι δημοσιεύσεις μπορούν να είναι διαφορετικά στον διακομιστή και τον υπολογιστή σας. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. Είμαστε έτοιμοι να το δημοσιεύσουμε ως μία εφαρμογή δικτύου! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Μετά επιλέξτε **Python 3.6**, και κάντε κλικ στο κουμπί Next για να ολοκληρώσετε τον οδηγό. + + > **Σημείωση** Σιγουρευτείτε να επιλέξετε την επιλογή "Manual configuration", όχι την "Django". Είμαστε πολύ κουλ για την προεπιλεγμένη PythonAnywhere Django εγκατάσταση. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Κάντε κλικ στο τσεκαρισμένο μπλε κουτί για να αποθηκεύσετε το μονοπάτι πριν συνεχίσετε. + + > **Note** Substitute your own PythonAnywhere username as appropriate. Εάν κάνετε ένα λάθος, το PythonAnywhere θα σας δείξει μια μικρή προειδοποίηση. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. Ο τρόπος που ρυθμίζουμε το PythonAnywhere να αναγνωρίζει τα Django blog μας είναι τροποποιώντας ένα αρχείο ρύθμισης παραμέτρων WSGI. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +Η δουλειά αυτού του αρχείου είναι να πει στο PythonAnywhere που ζει η εφαρμογή δικτύου μας και ποιο είναι το όνομα του αρχείου ρυθμίσεων Django. + +The `StaticFilesHandler` is for dealing with our CSS. Αυτό τακτοποιείται αυτόματα κατά την διάρκεια της τοπικής ανάπτυξης από την εντολή `runserver`. Θα μάθουμε λίγο περισσότερα για τα στατικά αρχεία αργότερα στο εγχειρίδιο, όταν θα επεξεργαστούμε το CSS για την ιστοσελίδα μας. + +Πατήστε **Save** και στη συνέχεια, επιστρέψτε στην καρτέλα **Web**. + +Είμαστε καθ'όλα έτοιμοι! Κλικάρετε το μεγάλο πράσινο κουμπί **Reload** και θα είστε σε θέση να δείτε την εφαρμογή σας. Θα βρείτε έναν σύνδεσμο σε αυτό στην κορυφή της σελίδας. + +## Συμβουλές για τον εντοπισμό σφαλμάτων + +Εάν εμφανιστεί ένα σφάλμα κατά την προσπάθειά σας να επισκεφθείτε την ιστοσελίδα σας, το πρώτο μέρος για να ψάξετε ορισμένες πληροφορίες εντοπισμού σφαλμάτων είναι στο αρχείο **error log**. Θα βρείτε ένα σύνδεσμο προς αυτό στην καρτέλα [Web](https://www.pythonanywhere.com/web_app_setup/) του PythonAnywhere. Δείτε εάν υπάρχουν κάποια μηνύματα σφάλματος εκεί. Τα πλέον συχνά εμφανίζονται στο κάτω μέρος. Τα πιο συνηθισμένα προβλήματα περιλαμβάνουν: + +- Ξεχνώντας ένα από τα βήματα που κάναμε στην κονσόλα: δημιουργία του virtualenv, ενεργοποίηση του, εγκατάσταση του Django σε αυτό, μετεγκατάσταση της βάσης δεδομένων. + +- Κάνοντας ένα λάθος στο μονοπάτι virtualenv στην καρτέλα Web- θα υπάρχει συνήθως ένα μικρό κόκκινο μήνυμα σφάλματος, εάν υπάρχει ένα πρόβλημα. + +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? + +- Πήρατε την ίδια έκδοση της Python για το virtualenv, όπως κάνατε για την εφαρμογή διαδικτύου; Και οι δύο θα πρέπει να είναι 3.6. + +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +Και να θυμάστε, ο εκπαιδευτής σας είναι εδώ να βοηθήσει! + +# Είστε συνδεδεμένοι! + +Η προεπιλεγμένη σελίδα για τον ιστότοπο σας πρέπει να λέει "Λειτουργεί!", όπως και στον τοπικό υπολογιστή σας. Δοκιμάστε να προσθέσετε το `/admin/` στο τέλος του URL, και θα μεταφερθείτε στην ιστοσελίδα διαχείρισης. Συνδεθείτε με το όνομα χρήστη και τον κωδικό πρόσβασης, και θα δείτε ότι μπορείτε να προσθέσετε νέες αναρτήσεις στο διακομιστή. + +Μόλις δημιουργήσετε μερικές δημοσιεύσεις, μπορείτε να πάτε πίσω στην τοπική σας εγκατάσταση (όχι το PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. Αυτό σας επιτρέπει να εργάζεστε και να πειραματίζεστε χωρίς να σπάσετε την ζωντανή σελίδα σας Web. Pretty cool, huh? + +Δώστε στον εαυτό σας ένα *ΜΕΓΑΛΟ* ελαφρύ χτύπημα στην πλάτη! Η εγκατάσταση σε έναν διακομιστή είναι ένα από τα πιο πολύπλοκα κομμάτια της ανάπτυξης εφαρμογών διαδικτύου και παίρνει συχνά αρκετές ημέρες στους ανθρώπους προτού να τις κάνουν λειτουργικές. Αλλά έχετε την ιστοσελίδα σας ζωντανή, στο πραγματικό Διαδίκτυο, ακριβώς όπως αυτό! \ No newline at end of file diff --git a/el/deploy/install_git.md b/el/deploy/install_git.md new file mode 100644 index 00000000000..869f21b3f4f --- /dev/null +++ b/el/deploy/install_git.md @@ -0,0 +1,52 @@ +Το Git είναι ένα «σύστημα ελέγχου έκδοσης» και χρησιμοποιείται από πολλούς προγραμματιστές. Αυτό το λογισμικό μπορεί να παρακολουθήσει τις αλλαγές στα αρχεία με την πάροδο του χρόνου έτσι ώστε να μπορείτε να ανακαλέσετε συγκεκριμένες εκδόσεις σε μεταγενέστερο στάδιο. Είναι κάτι σαν την δυνατότητα "παρακολούθησης αλλαγών" στο Microsoft Word, αλλά πολύ πιο ισχυρό. + +## Εγκαθιστώντας το Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Εκτός από αυτό, οι προκαθορισμένες ρυθμίσεις είναι σωστές. Επίσης η επιλογές Checkout Windows-style και Commit Unix-style κατά το τέλος μίας γραμμής είναι προτεινόμενες. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/el/deploy/signup_pythonanywhere.md b/el/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/el/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/el/django/README.md b/el/django/README.md new file mode 100644 index 00000000000..5f271803f30 --- /dev/null +++ b/el/django/README.md @@ -0,0 +1,27 @@ +# Τι είναι το Django; + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. Ένα πλαίσιο διαδικτύου είναι ένα σύνολο από στοιχεία που σας βοηθά να αναπτύξετε ιστοσελίδες πιο γρήγορα και εύκολα. + +Όταν κατασκευάζετε μία ιστοσελίδα, χρειάζεστε πάντα ένα παρόμοιο σύνολο στοιχείων: έναν τρόπο για να χειρίζεστε τον έλεγχο ταυτότητας χρήστη (εγγραφή, σύνδεση, αποσύνδεση), ένα πάνελ διαχείρισης για την ιστοσελίδα σας, φόρμες, έναν τρόπο για να ανεβάσετε αρχεία, κ.λπ. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Γιατί χρειάζεστε ένα πλαίσιο; + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Φανταστείτε ένα γραμματοκιβώτιο (θύρα), το οποίο παρακολουθείται για εισερχόμενα γράμματα (αιτήματα). Αυτό γίνεται από έναν διακομιστή διαδικτύου. The web server reads the letter and then sends a response with a webpage. Αλλά όταν θέλετε να στείλετε κάτι, πρέπει να έχει και κάποιο περιεχόμενο. Και το Django είναι κάτι που σας βοηθάει να δημιουργήσετε αυτό το περιεχόμενο. + +## Τι συμβαίνει όταν κάποιος ζητά μια ιστοσελίδα από το διακομιστή σας; + +Όταν ένα αίτημα φτάσει σε ένα διακομιστή δικτύου, περνάει στο Django το οποίο προσπαθεί να καταλάβει τι ζητείται στην πραγματικότητα. Λαμβάνει πρώτα μια διεύθυνση σελίδας δικτύου και προσπαθεί να καταλάβει τι να κάνει. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). Δεν είναι πολύ έξυπνο- παίρνει μια λίστα από μοτίβα και προσπαθεί να ταιριάξει την διεύθυνση URL. Το Django ελέγχει πρότυπα από πάνω προς τα κάτω και αν κάτι ταιριάζει, το Django μεταβιβάζει το αίτημα στην σχετική λειτουργία ( η οποία ονομάζεται *view*). + +Φανταστείτε μια ταχυδρόμο με ένα γράμμα. Περπατάει στην οδό και ελέγχει κάθε αριθμό σπιτιού αν είναι ίδιος με τον αντίστοιχο αριθμό στο γράμμα. Αν ταιριάζει, βάζει το γράμμα εκεί. Αυτός είναι ο τρόπος που λειτουργεί το urlresolver! + +Στην λειτουργία *view*, γίνονται όλα τα ενδιαφέροντα πράγματα: μπορούμε να δούμε μια βάση δεδομένων για να ψάξουμε για μερικές πληροφορίες. Μήπως ο χρήστης ζήτησε να αλλάξει κάτι στα δεδομένα; Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +Φυσικά, η παραπάνω περιγραφή είναι λίγο απλοποιημένη, αλλά δεν χρειάζεται να γνωρίζετε όλα τα τεχνικά ζητήματα ακόμη. Έχοντας μια γενική ιδέα είναι αρκετό. + +Έτσι αντί να αφιερώνουμε πάρα πολύ χρόνο σε λεπτομέρειες, θα ξεκινήσουμε απλά δημιουργώντας κάτι με το Django και θα μάθουμε όλα τα σημαντικά κομμάτια κατά μήκος του δρόμου! \ No newline at end of file diff --git a/el/django_admin/README.md b/el/django_admin/README.md new file mode 100644 index 00000000000..a9d81fa62ce --- /dev/null +++ b/el/django_admin/README.md @@ -0,0 +1,57 @@ +# Διαχείριση μέσω Django admin + +Για να προσθέσουμε, επεξεργαστούμε και να διαγράψουμε τις δημοσιεύσεις που έχουμε αναπτύξει, θα χρησιμοποιήσουμε τον διαχειριστή Django. + +Ας ανοίξουμε το αρχείο `blog/admin.py` και ας αντικαταστήσουμε τα περιεχόμενα του με αυτό: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +Με τον παραπάνω κώδικα, εισάγουμε το μοντέλο Post (δηλαδή τον πίνακα της βάσης με όνομα Post) όπως ορίστηκε από το προηγούμενο κεφάλαιο. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +Εντάξη λοιπόν αγαπητοί κύριοι και κυρίες, ας ρίξουμε μια ματία στο Post μοντέλο μας. Θυμηθείτε ότι πρέπει πρώτα να πληκτρολογήσουμε `python manage.py runserver` στην κονσόλα μας ώστε να ξεκινήσει ο σερβερ μας. Go to your browser and type the address http://127.0.0.1:8000/admin/. Θα δείτε μία σελίδα σύνδεσης όπως αυτή: + +![Login page](images/login_page2.png) + +Για να συνδεθείτε, χρειάζεται να δημιουργήσετε ένα *superuser*- ένα λογαριασμό χρήστη ο οποίος έχει δικαιώματα σε οτιδήποτε σε αυτή την σελίδα. Πηγαίνετε πίσω στην γραμμή εντολών, πληκτρολογήστε `python manage.py createsuperuser`, και πατήστε enter. + +> Θυμηθείτε, για να γράψετε νέες εντολές ενώ ο διακομιστής του ιστότοπου εκτελείται, ανοίξτε ένα νέο παράθυρο ακροδέκτη και ενεργοποιήστε το virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/el/django_forms/README.md b/el/django_forms/README.md new file mode 100644 index 00000000000..ce838756499 --- /dev/null +++ b/el/django_forms/README.md @@ -0,0 +1,447 @@ +# Φόρμες Django + +Το τελευταίο που έμεινε για την ιστοσελίδα μας είναι να δημιουργήσουμε μια όμορφη φόρμα για την εισαγαγωγή και τροποποίηση των blog post μας. Θα μπορούσαμε να χρησιμοποιήσουμε το Django `admin` αλλά είναι αρκετά πολύπλοκο να τροποποιήσουμε και να ωραιοποιήσουμε την φόρμα εισαγωγής. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +Μία από τις ευκολίες των Django φορμών είναι ότι μπορούμε να ξεκινήσουμε από το μήδεν ή να χρησιμοποιήσουμε το `ModelForm` που ουσιαστικά αποθηκεύει τα δεδομένα της φόρμας στο μοντέλο (ή διαφορετικά στο σωστό πίνακα της βάσης μας). + +Αυτό είναι ακριβώς που θέλουμε να κάνουμε δηλαδή να δημιουργήσουμε εύκολα μια φόρμα εισαγωγής δεδομένων για το ήδη προυπάρχων `Post` μοντέλο. + +Οπώς κάθε άλλο σημαντικό τμήμα του Django, οι φόρμες εισαγωγής "ζούν" στο δικό τους αρχείο: `forms.py`. + +Πρέπει να δημιουργήσουμε το αρχείο forms. py μέσα στην ντερέκτρορη `blog`. + + blog + └── forms.py + + +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Πρέπει να εισάγουμε αρχικά το module forms του Django (`from django import forms`) και φυσικά το μοντέλο `Post` (`from .models import Post`). + +Οπώς πιθανόν να υποψιάζεστε το `PostForm`, είναι το όνομα της φόρμας εισαγωγής. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Στην συνέχεια, έχουμε `class Meta`, όπου "λέμε" στο Django για ποίο μοντέλο πρέπει να δημιουργήσει την φόρμα εισαγωγής δεδομένων). + +Τέλος, πρέπει να ορίσουμε ποίο/α πεδίο/α πρέπει να διαθέσουμε στην φόρμα μας. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +Αυτό ήταν! Αυτό που μας απομένει είναι να χρησιμοποιήσουμε την φόρμα μας μέσα σε ένα *view* ώστε να είναι διαθεσίμη μέσω ενός template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Πως συνδέουμε μια σελίδα με την φόρμα μας + +Ανοίξτε το αρχείο `blog/templates/blog/base.html`. Θα προσθέσουμε το λινκ μέσα στο `div` με όνομα `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? + +## URL + +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. Θα επιστρέψουμε σε αυτή την *άποψη*, αλλά για τώρα, ας δημιουργήσουμε γρήγορα ένα πρότυπο για την αίτηση. + +## Πρότυπο + +Πρέπει να δημιουργήσουμε ένα αρχείο `post_edit.html` στο κατάλογο `blog/templates/blog`. Για να κάνουμε μια αίτηση εργασίας χρειαζόμαστε αρκετά πράγματα: + +* Πρέπει να εμφανίσουμε την αίτηση. Μπορούμε να το κάνουμε αυτό με (για παράδειγμα) {% raw %}`{{ form.as_p }}`{% endraw %}. +* Η παραπάνω γραμμή πρέπει να τυλιχθεί με μία ετικέτα αίτησης HTML: `...`. +* Χρειαζόμαστε ένα κουμπί `Αποθήκευση`. Το κάνουμε αυτό με ένα κουμπί HTML: ``. +* Και στο τέλος, ακριβώς μετά την ετικέτα ανοίγματος `
` πρέπει να προσθέσουμε {% raw %}`{% csrf_token %}`{% endraw %}. Αυτό είναι πολύ σημαντικό, αφού καθιστά τις αιτήσεις σας ασφαλείς! Εάν ξεχάσετε αυτό το κομμάτι, το Django θα παραπονεθεί όταν προσπαθήσετε να αποθηκεύσετε την αίτηση: + +![CSFR Απαγορευμένη σελίδα](images/csrf2.png) + +Εντάξει, ας δούμε πως το HTML στο `post_edit.html` πρέπει να δείχνει: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Ώρα να ανανεώσετε! Ναι! Η αίτηση σας εμφανίζεται! + +![Νέα αίτηση](images/new_form2.png) + +Αλλά, περιμένετε ένα λεπτό! Όταν πληκτρολογείτε κάτι στα πεδία `τίτλο` και `κείμενο`και προσπαθήσετε να το αποθηκεύσετε, τι θα συμβεί; + +Τίποτα! Είμαστε άλλη μια φορά στην ίδια σελίδα και το κείμενο μας έχει εξαφανιστεί... και δεν έχει προστεθεί καμία νέα δημοσίευση, Οπότε τι πήγε λάθος; + +Η απάντηση είναι: τίποτα. Πρέπει να κάνουμε λίγη περισσότερη δουλειά στο *προβολή* μας. + +## Αποθηκεύοντας την αίτηση + +Ανοίξτε `blog/views.py` ξανά. Προς το παρόν αυτό που έχουμε στο `post_new` θέα είναι τα ακόλουθα: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Όταν υποβάλουμε την αίτηση, επανερχόμαστε στην ίδια θέα, αλλά αυτή τη φορά έχουμε περισσότερα δεδομένα στο `αίτημα`, πιο συγκεκριμένα στο `αίτηση.POST` (το όνομα δεν έχει να κάνει με μία "δημοσίευση" blog, έχει να κάνει με το γεγονός ότι "δημοσιεύουμε" δεδομένα). Θυμηθείτε πως στον φάκελο HTML, ο `
` ορισμός μας είχε την μεταβλητή `method="POST"`; Όλα τα πεδία από την αίτηση είναι στο `request.POST`. Δεν πρέπει να μετονομάσετε το `POST` σε οτιδήποτε άλλο ( η μόνο άλλη έγκυρη τιμή για το `method` είναι `GET`, αλλά δεν έχουμε χρόνο για να εξηγήσουμε ποια είναι η διαφορά). + +Έτσι στο *view* έχουμε δύο ξεχωριστές καταστάσεις να διαχειριστούμε: πρώτον, όταν αποκτούμε πρόσβαση στην σελίδα για πρώτη φορά και θέλουμε μία άδεια αίτηση, και δεύτερον, όταν πάμε πίσω στο *view* με όλα τα δεδομένα αίτησης που μόλις πληκτρολογήσαμε. Επομένως, πρέπει να προσθέσουμε μια συνθήκη ( θα χρησιμοποιήσουμε `if` για αυτό): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +Είναι καιρός να συμπληρώσουμε τις τελείες `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? Θα το κάνουμε αυτό όπως ακολουθεί: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +Το επόμενο πράγμα είναι να ελέγξουμε αν η αίτηση είναι σωστή ( όλα τα απαιτούμενα πεδία έχουν οριστεί και δεν έχουν υποβληθεί εσφαλμένες τιμές). Το κάνουμε αυτό με `form.is_valid()`. + +Ελέγχουμε αν η αίτηση είναι έγκυρη και αν ναι, μπορούμε να την αποθηκεύσουμε! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Βασικά, έχουμε δύο πράγματα εδώ: αποθηκεύουμε την αίτηση με `form.save` και προσθέτουμε έναν συγγραφέα ( μιας και δεν υπήρχε πεδίο `συγγραφέα` στο `PostForm` και αυτό το πεδίο είναι απαραίτητο). `commit=False` σημαίνει ότι δεν θέλουμε να αποθηκεύσουμε το μοντέλο `Post` ακόμα - θέλουμε να προσθέσουμε τον αναγνώστη πρώτα. Τις περισσότερες φορές θα χρησιμοποιήσετε το `form.save()` χωρίς το `commit=False`, αλλά σε αυτή την περίπτωση, πρέπει να το προμηθεύσουμε. `post.save()` θα διατηρήσει τις αλλαγές (προσθέτοντας τον συγγραφέα) και δημιουργείται ένα νέο blog post! + +Τέλος, θα ήταν τρομερό εάν μπορούσαμε να πάμε αμέσως στην `post_detail` σελίδα για το νεοσυσταθέν blog post μας, σωστά; Για να το κάνουμε αυτό χρειαζόμαστε μια ακόμα είσοδο: + +{% filename %}blog/views.py{% endfilename %} + +```python +από ανακατεύθυνση εισαγωγής django.shortcuts +``` + +Προσθέστε το στην αρχή του αρχείου σας. Και τώρα μπορούμε να πούμε, "πηγαίνετε στη `post_detail` σελίδα για το νεοσυσταθέν post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` είναι το όνομα της προβολής στο οποίο θέλουμε να πάμε. Θυμηθείτε ότι αυτή η *άποψη * απαιτεί μία μεταβλητή `pk`; Για να το περάσουμε στις απόψεις, χρησιμοποιούμε `pk=post.pk`, όπου `post` είναι το νεοσύστατο blog post! + +Εντάξει. έχουμε μιλήσει πολύ. αλλά μάλλον θέλουμε να δούμε πως μοιάζει το *view*, σωστά; + +{% filename %}blog/views.py{% endfilename %} + +```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/, προσθέστε ένα `τίτλο` και `κείμενο`, αποθηκεύστε το… και voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```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` we add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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` προβολή, σωστά; Αλλά όχι εντελώς. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +… και όταν έχουμε μόλις ανοίξει μία αίτηση με αυτή τη δημοσίευση για να επεξεργαστούμε: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +Εντάξει, ας δοκιμάσουμε αν λειτουργεί! Πάμε στην σελίδα `post_detail`. Θα πρέπει να υπάρχει ένα κουμπί επεξεργασίας στην πάνω δεξιά γωνία: + +![Κουμπί επεξεργασίας](images/edit_button2.png) + +Όταν κάνετε κλικ θα δείτε την φόρμα με την δημοσίευση στο blog μας: + +![Επεξεργαστείτε αίτηση](images/edit_form2.png) + +Νιώστε ελεύθεροι να αλλάξετε τον τίτλο η το κείμενο και να αποθηκεύσετε τις αλλαγές! + +Συγχαρητήρια! Η εφαρμογή σας γίνεται όλο και πιο πλήρης! + +Εάν χρειάζεστε περισσότερες πληροφορίες για τις φόρμες Django, θα πρέπει να διαβάσετε τα έγγραφα: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## Ασφάλεια + +Το να μπορείς να δημιουργήσεις νέες δημοσιεύσεις κάνοντας απλώς ένα κλικ σε ένα σύνδεσμο είναι φοβερό! Αλλά τώρα, οποιοσδήποτε επισκεφθεί την σελίδα σας θα μπορεί να φτιάξει μία καινούρια δημοσίευση blog, και αυτό είναι κάτι που πιθανώς δεν θέλετε. Ας το κάνουμε έτσι ώστε το κουμπί εμφανίζεται για εσάς αλλά για κανέναν άλλο. + +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Πρόκειται να προσθέσουμε άλλη μία ετικέτα `{% if %}` σε αυτό, το οποίο θα κάνει τον σύνδεσμο να εμφανίζεται μόνο για χρήστες που είναι συνδεδεμένοι στον διαχειριστή. Προς το παρόν, είστε μόνο εσείς! Αλλάξτε την ετικέτα `` να μοιάζει σαν αυτό: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Αυτό `{% if %}` θα προκαλέσει τον σύνδεσμο να σταλθεί στο πρόγραμμα περιήγησης μόνο αν ο χρήστης που ζητά την σελίδα είναι συνδεδεμένος. Αυτό δεν προστατεύει την δημιουργία νέων δημοσιεύσεων εντελώς, αλλά είναι ένα καλό πρώτο βήμα. Θα καλύψουμε περισσότερη ασφάλεια στα μαθήματα επέκτασης. + +Θυμάστε το εικονίδιο επεξεργασίας που μόλις προσθέσαμε στην σελίδα λεπτομερειών; Θέλουμε επίσης να προσθέσουμε την ίδια αλλαγή εκεί, ώστε άλλα άτομα δεν θα μπορούν να επεξεργαστούν τις υπάρχουσες δημοσιεύσεις. + +Ανοίξτε το `blog/templates/blog/post_detail.html` και βρείτε αυτή τη γραμμή: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Αλλάξτε το σε αυτό: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Μιας και είστε πιθανότατα συνδεδεμένοι, εάν ανανεώσετε την σελίδα, δεν θα δείτε τίποτα διαφορετικό. Φορτώστε την σελίδα σε ένα διαφορετικό πρόγραμμα περιήγησης ή ένα παράθυρο ανώνυμης περιήγησης ( που ονομάζεται "InPrivate" στο Windows Edge), όμως, και θα δείτε ότι ο σύνδεσμος δεν εμφανίζεται, ούτε και το εικονίδιο! + +## Ένα πράγμα ακόμα: ώρα να αναπτύξετε! + +Για να δούμε αν όλα αυτά λειτουργούν στο PythonAnywhere. Ώρα για άλλη μια ανάπτυξη! + +* Πρώτα, δεσμεύστε τον νέο σας κωδικό, και βάλτε τον στο GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +Και αυτό είναι! Συγχαρητήρια :) \ No newline at end of file diff --git a/el/django_installation/README.md b/el/django_installation/README.md new file mode 100644 index 00000000000..8bd1a1f96a1 --- /dev/null +++ b/el/django_installation/README.md @@ -0,0 +1,7 @@ +# Εγκατάσταση του Django + +> **Σημείωση** Αν χρησιμοποιείτε ένα Chromebook, παραλείψτε αυτό το κεφάλαιο και σιγουρευτείτε ότι ακουλουθείτε τις [Chromebook Setup](../chromebook_setup/README.md) οδηγίες. +> +> **Σημείωση** αν έχετε ήδη περάσει τα βήματα εγκατάστασης τότε το έχετε ήδη κάνει αυτό - μπορείτε να πάτε απευθείας στο επόμενο κεφάλαιο! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/el/django_installation/instructions.md b/el/django_installation/instructions.md new file mode 100644 index 00000000000..f69041c8c8a --- /dev/null +++ b/el/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Μέρος αυτής της ενότητας βασίζεται στα σεμινάρια από τα Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Εικονικό περιβάλλον + +Πρίν να εγκαταστήσουμε το Django, θα εγκαταστήσουμε ενα εξαιρετικά χρήσιμο εργαλείο για να κρατίσουμε το περιβάλλον του υπολογιστή σου τακτοποιημένο. Μπορείς να παραλείψεις αυτό το βήμα, αλλά συστήνουμε να το ακολουθήσεις. Ξεκινώντας με το καλύτερο δυνατό περιβάλλον, θα αποφύγεις πολλά προβλήματα στο μέλλον! + +Λοιπόν, ας δημιουργήσουμε ενα ** εικονικό περιβάλλον** (το αποκαλούμενο *virtualenv*). Το virtualenv θα απομονώσει την κάθε εγκατάσταση Python/Django ανά έργο. Αυτό σημαίνει οι αλλαγές που κάνεις σε μια ιστιοσελίδα δεν επηρεάζουν οποιεσδήποτε άλλες ιστιοσελίδες που επίσης αναπτύσσεις παράλληλα. Καλό, ε; + +Το μόνο που χρειάζεται να κάνεις είναι να βρείς έναν κατάλογο στον οποίο θέλεις να δημιουργήσεις το `virtualenv`. Το home directory σου, για παράδειγμα. Στα Windows, θα μοιάζει κάπως έτσι `C:\Users\Name` ( όπου `Name` είναι το όνομα της σύνδεσης σας). + +> **ΣΗΜΕΙΩΣΗ:** Στα Windows, σιγουρευτείτε ότι αυτός ο κατάλογος δεν περιέχει χαρακτήρες που τονίζονται ή ειδικούς χαρακτήρες, αν το όνομα χρήστη σας περιέχει χαρακτήρες που τονίζονται, χρησιμοποιείστε ένα διαφορετικό κατάλογο, για παράδειγμα, `C:\djangogirls`. + +Για αυτό το tutorial θα χρησιμοποιήσουμε ένα νεο κατάλογο `djangogirls` από το home directory σου: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +Θα δημιουργήσουμε ένα virtualenv που ονομάζεται `myvenv`. Η γενική εντολή είναι: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Όπου `myvenv` είναι το όνομα του `virtualenv` σας. Μπορείς να χρησιμοποιήσεις οποιοδήποτε άλλο όνομα, αλλά πρέπει να είναι σε πεζά, χωρίς κενά, εμφάσεις ή ειδικούς χαρακτήρες. Είναι επίσης καλή ιδέα να κρατήσετε το όνομα μικρό - θα το αναφέρετε συχνά! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +Το `myvenv` είναι το όνομα του `virtualenv` σου. Μπορείς να χρησιμοποιήσεις οποιοδήποτε άλλο όνομα, αλλα πρέπει να είναι σε πεζά και χωρίς κενά. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Το εικονικό περιβάλλον δεν δημιουργήθηκε επιτυχώς επειδή το ensurepip δεν είναι διαθέσιμο. Στα συστήματα Debian/Ubuntu, πρέπει να εγκαταστήσετε το πακέτο python3-venv χρησιμοποιώντας την ακόλουθη εντολή. +> apt-get install python3-venv +> Μπορεί να χρειαστεί να χρησιμοποιήσετε το sudo με αυτή την εντολή. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Δουλεύοντας με το virtualenv + +Η παραπάνω εντολή θα δημιουργήσει ένα κατάλογο που ονομάζεται `myvenv` (ή όποιο άλλο όνομα διαλέξετε) που περιέχει το εικονικό μας περιβάλλον (βασικά ένα μάτσο καταλόγων και αρχείων). + + + +Ξεκινήστε το εικονικό σας περιβάλλον εκτελώντας: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **ΣΗΜΕΙΩΣΗ:** στα Windows 10 μπορεί να λάβετε ένα σφάλμα στο Windows PowerShell που λέει ` η εκτέλεση των σεναρίων έχει απενεργοποιηθεί σε αυτό το σύστημα `. Σε αυτή την περίπτωση, ανοίξτε ένα άλλο Windows PowerShell με την επιλογή "Εκτέλεση ως διαχειριστής". Έπειτα δοκιμάστε να πληκτρολογήσετε την ακόλουθη εντολή πριν ξεκινήσετε το εικονικό περιβάλλον σας: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Αλλάζοντας την πολιτική εκτέλεσης μπορεί να σας εκθέσει σε ρίσκα ασφάλειας που περιγράφονται στο θέμα βοήθειας about_Execution_Policies στο http://go.microsoft.com/fwlink/?LinkID=135170. Θέλετε να αλλάξετε την πολιτική εκτέλεσης; [Y] Ναι [A] Ναι σε όλα [N] Όχι [L] Όχι σε όλα [S] Διακοπή [?] Βοήθεια (προεπιλεγμένο είναι το "N"): A +> + + + + + +Ξεκινήστε το εικονικό σας περιβάλλον εκτελώντας: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Θυμηθείτε να αντικαταστήσετε το `myvenv` με το επιλεγμένο `virtualenv` όνομα σας! + +> **ΣΗΜΕΙΩΣΗ:** μερικές φορές `πηγή` μπορεί να μην είναι διαθέσιμη. Σε αυτές τις περιπτώσεις προσπαθήστε να κάνετε αυτό: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +Θα ξέρετε ότι έχετε ξεκινήσει το `virtualenv` όταν δείτε ότι γραμμή εντολών στην κονσόλα σας είναι προκαθορισμένη με `(myvenv)`. + +Όταν δουλεύετε μέσα σε ένα εικονικό περιβάλλον, `python` θα αναφέρετε αυτόματα στην σωστή έκδοση ώστε να μπορείτε να χρησιμοποιήσετε `python` αντί για `python3`. + +Εντάξει, έχουμε τοποθετήσει όλες τις σημαντικές εξαρτήσεις. Μπορούμε επιτέλους να εγκαταστήσουμε το Django! + +## Εγκατάσταση Django + +Τώρα που έχετε ξεκινήσει το `virtualenv` σας, μπορείτε να εγκαταστήσετε το Django. + +Πριν κάνουμε αυτό, πρέπει να σιγουρευτούμε ότι έχουμε την τελευταία έκδοση του `pip`, το λογισμικό που χρησιμοποιούμε για να εγκαταστήσουμε το Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> Εάν λάβετε ένα σφάλμα όταν καλείται το μπιπ στην πλατφόρμα Windows, παρακαλούμε ελέγξτε εάν το μονοπάτι ονόματος του έργου σας περιέχει κενά, εμφάσεις ή ειδικούς χαρακτήρες (για παράδειγμα,`C:\Users\User Name\djangogirls`). Εάν το κάνει, παρακαλώ σκεφτείτε να χρησιμοποιήσετε μία άλλη θέση χωρίς κενά, εμφάσεις ή ειδικούς χαρακτήρες (πρόταση: `C:\djangogirls`). Δημιουργήστε ένα νέο virtualenv στον νέο κατάλογο, μετά σβήστε τον παλιό και δοκιμάστε την παραπάνω εντολή ξανά. (Το να μετακινήσετε τον κατάλογο virtualenv δεν θα δουλέψει μιας και το virtualenv χρησιμοποιεί απόλυτες διαδρομές.) + + + + + +> Η γραμμή εντολών σας μπορεί να παγώσει αφού προσπαθήσετε να εγκαταστήσετε το Django. Εάν γίνει αυτό, αντί για την παραπάνω εντολή χρησιμοποιήστε: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +Αυτό είναι! Είστε (επιτέλους) έτοιμοι να δημιουργήσετε μια εφαρμογή Django! \ No newline at end of file diff --git a/el/django_models/README.md b/el/django_models/README.md new file mode 100644 index 00000000000..7ba4cd1e323 --- /dev/null +++ b/el/django_models/README.md @@ -0,0 +1,200 @@ +# Μοντέλα (models) του Django + +Αυτό που θέλουμε να δημιουργήσουμε τώρα είναι κάτι που θα αποθηκεύει όλες τις αναρτήσεις του blog μας. Αλλά για να είμαστε σε θέση να το κάνουμε, πρέπει να μιλήσουμε λίγο για το τι ονομάζουμε `"αντικείμενα" (objects)`. + +## Αντικείμενα (objects) + +Υπάρχει μια έννοια στον προγραμματισμό που ονομάζεται `"Αντικειμενοστραφής προγραμματισμός`. Η ιδέα είναι ότι αντί να γράφετε τα πάντα ως μια βαρετή ακολουθία από προγραμματιστικές εντολές, μπορούμε να μοντελοποιήσουμε τα πράγματα και να καθορίσουμε πως αλληλεπιδρούν μεταξύ τους. + +Άρα, τι είναι ένα αντικείμενο; Είναι μια συλλογή από ιδιότητες και συμπεριφορές. Ακούγεται παράξενο, αλλά θα σας δώσουμε ένα παράδειγμα. + +Εάν θέλουμε να μοντελοποιήσουμε μια γάτα, θα δημιουργήσουμε ένα αντικείμενο `Γάτα` το οποίο έχει κάποιες ιδιότητες όπως `χρώμα`, `ηλικία`, `διάθεση` (όπως καλή, κακή, νυσταγμένη :)), και `ιδιοκτήτης`(που θα μπορεί να ανατεθεί σε ένα αντικείμενο `άτομο` - ή ίσως, στην περίπτωση μιας αδέσποτης γάτας, αυτή η ιδιότητα θα μπορούσε να είναι άδεια). + +Έπειτα η `γάτα` έχει κάποιες δράσεις `γουργούρισμα`, `ξύσιμο` ή `τάισμα`( σε αυτή την περίπτωση, θα δώσουμε στην γάτα λίγη `γατοτροφή`, που θα μπορούσε να είναι ένα ξεχωριστό αντικείμενο με ιδιότητες, όπως `γεύση`). + + Γάτα + _________ + χρώμα + ηλικία + συμπεριφορά + ιδιοκτήτης + γουργούρισμα() + ξύσιμο() + τάισμα(γατο_τροφή) + + + Γατοτροφή + __________ + + γεύση + + +Έτσι, βασικά η ιδέα είναι να περιγράψουμε τα αληθινά πράγματα στον κώδικα με ιδιότητες (που ονομάζονται `ιδιότητες αντικειμένου`) και συμπεριφορές (που ονομάζονται `μέθοδοι αντικειμένου`). + +Πώς θα μοντελοποιήσουμε τότε τις αναρτήσεις του blog; Θέλουμε να κατασκευάσουμε ένα blog, σωστά; + +Πρέπει να δώσουμε απάντηση στο ερώτημα: τι είναι μία ανάρτηση στο blog; Τι ιδιότητες πρέπει να έχει; + +Λοιπόν, σίγουρα μία ανάρτηση στο blog μας χρειάζεται κάποιο κείμενο με το περιεχόμενό του και έναν τίτλο, σωστά; Θα ήταν επίσης ωραίο να ξέρουμε ποιος το έγραψε αυτό - έτσι χρειαζόμαστε ένα συγγραφέα. Τέλος, θέλουμε να γνωρίζουμε πότε δημιουργήθηκε και δημοσιεύτηκε η συγκεκριμένη ανάρτηση. + + Post + -------- + title + text + author + created_date + published_date + + +Τι είδους πράγματα θα μπορούσαν να γίνουν με μια ανάρτηση στο blog; Θα ήταν ωραίο να έχουμε κάποια `μέθοδο` που δημοσιεύει την ανάρτηση, σωστά; + +Έτσι, θα χρειαστούμε μια μέθοδο `publish`. + +Δεδομένου ότι γνωρίζουμε ήδη τι θέλουμε να επιτύχουμε, ας ξεκινήσουμε τη μοντελοποίηση στο Django! + +## Μοντέλο του Django + +Γνωρίζοντας τι είναι ένα αντικείμενο, μπορούμε να δημιουργήσουμε ένα μοντέλο Django για την ανάρτηση στο blog μας. + +Ένα μοντέλο στο Django είναι ένα ιδιαίτερο είδος αντικειμένου- αποθηκεύεται στο `database`. Η βάση δεδομένων είναι μια συλλογή δεδομένων. Είναι εκεί όπου θα αποθηκεύεις πληροφορίες για τους χρήστες σου, τις αναρτήσεις στο blog, κλπ. Θα χρησιμοποιήσουμε την βάση δεδομένων SQLite για την αποθήκευση των δεδομένων μας. Αυτός είναι ο προεπιλεγμένος μετασχηματιστής βάσης δεδομένων Django - είναι αρκετό για εμάς για τώρα. + +Μπορείς να σκεφτείς ένα μοντέλο της βάσης δεδομένων ως ένα υπολογιστικό φύλλο με στήλες (πεδία) και γραμμές (δεδομένα). + +### Δημιουργία μιας εφαρμογής + +Για να κρατήσουμε τα πάντα τακτοποιημένα, θα δημιουργήσουμε μια ξεχωριστή εφαρμογή μέσα στο project μας. Είναι πολύ ωραίο να έχουμε τα πάντα οργανωμένα από την αρχή. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +Θα παρατηρήσετε ότι ένας νέος`blog` κατάλογος δημιουργείται και περιέχει έναν αριθμό αρχείων. Οι κατάλογοι και τα αρχεία στο έργο μας πρέπει να μοιάζουν κάπως έτσι: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +Μετά την δημιουργία μίας εφαρμογής, πρέπει επίσης να πούμε στο Django ότι πρέπει να το χρησιμοποιήσει. Αυτό το κάνουμε στο αρχείο `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. Έτσι το τελικό προϊόν πρέπει να μοιάζει κάπως έτσι: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField`- αυτό είναι για μεγάλα κείμενα χωρίς ένα όριο. Ακούγεται ιδανικό για περιεχόμενο δημοσιεύσεων blog, έτσι δεν είναι; +- `models.DateTimeField`- αυτό είναι μια ημερομηνία και ώρα. +- `models.ForeignKey`- αυτό είναι ένας σύνδεσμος για ένα άλλο μοντέλο. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +What about `def publish(self):`? Αυτή είναι ακριβώς η μέθοδος `publish` για την οποία μιλούσαμε πριν. `def` σημαίνει ότι είναι αυτή είναι μια λειτουργία/μέθοδος και `publish` είναι το όνομα της μεθόδου. Μπορείτε να αλλάξετε το όνομα της μεθόδου αν θέλετε. Ο κανόνας ονομασίας είναι ότι χρησιμοποιούμε μικρά γράμματα και κάτω παύλες αντί για κενά. Για παράδειγμα, μια μέθοδος που υπολογίζει την μέση τιμή θα λεγόταν `υπολογισμός_μέσης_τιμής`. + +Οι μέθοδοι συχνά `επιστρέφουν` κάτι. Υπάρχει ένα παράδειγμα αυτού στη μέθοδο `__str__`. Σε αυτό το σενάριο, όταν καλούμε την `__str__()` θα λάβουμε ένα κείμενο (**string**) με ένα τίτλο θέσης. + +Επίσης προσέξτε ότι και το `def publish(self):` και το `def __str__(self):` "χτυπημένα" μέσα στην κλάση μας. Επειδή η Python είναι ευαίσθητη στο whitespace, πρέπει να "χτυπήσουμε" τις μεθόδους μας μέσα στην κλάση. Αλλιώς, οι μέθοδοι δεν θα ανήκουν στην κλάση, και μπορεί να συναντήσετε απρόοπτη συμπεριφορά. + +Εάν κάτι ακόμα δεν είναι ξεκάθαρο σχετικά με τα μοντέλα, μη διστάσετε να ρωτήσετε τον καθηγητή σας! Ξέρουμε ότι είναι περίπλοκο, ειδικά όταν μαθαίνετε τι είναι τα αντικείμενα και οι λειτουργίες ταυτόχρονα. But hopefully it looks slightly less magic for you now! + +### Δημιουργήστε πίνακες για πρότυπα στην βάση δεδομένων σας + +Το τελευταίο βήμα εδώ είναι να προσθέσουμε το νέο μοντέλο μας στην βάση δεδομένων μας. Πρώτα πρέπει να ενημερώσουμε το Django ότι έχουμε κάποιες αλλαγές στο μοντέλο μας. (Μόλις το δημιουργήσαμε!) Πηγαίνετε στο παράθυρο της κονσόλας σας και πληκτρολογήστε `python manage.py makemigrations blog`. Θα μοιάζει κάπως έτσι: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Σημείωση:** Θυμηθείτε να αποθηκεύετε τα αρχεία που επεξεργάζεστε. Αλλιώς, ο υπολογιστής σας θα εκτελέσει τις προηγούμενες εκδόσεις που μπορεί να σας δώσει μηνύματα απρόοπτων σφαλμάτων. + +Το Django προετοίμασε ένα φάκελο μετανάστευσης για εμάς που πρέπει τώρα να εφαρμόσουμε στην βάση δεδομένων μας. Πληκτρολογήστε `python manage.py migrate blog` και τα αποτελέσματα πρέπει να είναι όπως ακολουθεί: + +{% filename %}command-line{% endfilename %} + + (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 + + +Ζήτω! Το μοντέλο ανάρτησης μας είναι στην βάση δεδομένων μας! Θα ήταν ωραίο να το δούμε, σωστά; Πηγαίνετε στο επόμενο κεφάλαιο για να δείτε πως μοιάζει η ανάρτηση σας! \ No newline at end of file diff --git a/el/django_orm/README.md b/el/django_orm/README.md new file mode 100644 index 00000000000..4fb48d881d2 --- /dev/null +++ b/el/django_orm/README.md @@ -0,0 +1,218 @@ +# Django ORM και QuerySets + +Σε αυτό το κεφάλαιο θα μάθετε πως το Django συνδέεται στην βάση δεδομένων και αποθηκεύει δεδομένα μέσα της. Ας ξεκινήσουμε! + +## Τι είναι ένα QuerySet; + +Ένα QuerySet είναι, στην ουσία, μία λίστα αντικειμένων ενός δοθέν Μοντέλου. Τα QuerySets σας επιτρέπουν να διαβάσετε τα δεδομένα από την βάση δεδομένων, να τα φιλτράρετε και να τα ταξινομήσετε. + +Είναι πιο εύκολο να μάθεις κάνοντας. Πάμε να δοκιμάσουμε; + +## Παράθυρο εντολών Django + +Άνοιξε την τοπική σου κονσόλα (όχι στο PythonAnywhere) και πληκτρολόγησε αυτήν την εντολή: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +Το αποτέλεσμα πρέπει να είναι σαν αυτό: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +Είστε τώρα στην διαδραστική κονσόλα του Django. Είναι ακριβώς όπως το παράθυρο εντολών της Python, αλλά με μερική επιπρόσθετη μαγεία Django. :) Μπορείτε να χρησιμοποιήσετε όλες τις εντολές Python εδώ επίσης, φυσικά. + +### Όλα τα αντικείμενα + +Ας προσπαθήσουμε να εμφανίσουμε όλες τις δημοσιεύσεις του blog μας πρώτα. Μπορείς να το κάνεις με την ακόλουθη εντολή: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Ωχ! Εμφανίστηκε ένα λάθος, μας λέει ότι δεν υπάρχει καμία δημοσίευση. Είναι σωστό- ξεχάσαμε να το εισάγουμε πρώτα! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +Εισάγουμε το μοντέλο `Post` from `blog.models`. Ας προσπαθήσουμε να εμφανίσουμε όλες τις αναρτήσεις ξανά: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +Αυτή είναι μια λίστα των αναρτήσεων που δημιουργήσαμε νωρίτερα! Δημιουργήσαμε αυτές τις αναρτήσεις χρησιμοποιώντας το περιβάλλον διαχειριστή Django. Αλλά τώρα θέλουμε να δημιουργήσουμε νέες αναρτήσεις χρησιμοποιώντας την Python, οπότε πως το κάνουμε αυτό; + +### Δημιουργία αντικειμένου + +Έτσι δημιουργείτε ένα νέο αντικείμενο Ανάρτηση στην βάση δεδομένων: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Αλλά μας λείπει ένα συστατικό εδώ: `εγώ`. Χρειαζόμαστε να περάσουμε μία παρουσία του μοντέλου `Χρήστη` ως συγγραφέα. Πως το κάνουμε αυτό; + +Ας εισάγουμε το μοντέλο Χρήστη πρώτα: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +Τι χρήστες έχουμε στην βάση δεδομένων μας; Δοκιμάστε αυτό: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +Αυτός είναι ο υπέρ-χρήστης που δημιουργήσαμε νωρίτερα! Ας λάβουμε μία παρουσία του χρήστη τώρα: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Ζήτω! Θέλετε να ελέγξετε αν λειτούργησε; + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +Αυτό είναι, άλλη μια δημοσίευση στην λίστα! + +### Προσθέστε περισσότερες δημοσιεύσεις + +Τώρα μπορείτε να διασκεδάσετε λίγο και να προσθέσετε περισσότερες δημοσιεύσεις για να δείτε πως δουλεύει. Προσθέστε δυο-τρεις ακόμα και μετά προχωρήστε στο επόμενο μέρος. + +### Φιλτράρισμα αντικειμένων + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Ordering objects + +Τα QuerySets επίσης σου επιτρέπουν να ταξινομήσεις την λίστα των αντικειμένων. Ας προσπαθήσουμε να τα ταξινομήσουμε με το πεδίο `ημερομηνία_δημιουργίας`: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +Μπορούμε επίσης να αντιστρέψουμε την ταξινόμηση προσθέτοντας `-` στην αρχή: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Αλυσιδωτά QuerySets + +Μπορείτε επίσης να συνδυάσετε QuerySets με το να τα **αλυσοδέσετε** μαζί: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +Αυτό είναι πολύ ισχυρό και σας επιτρέπει να γράψετε αρκετά σύνθετα ερωτήματα. + +Ωραία! Τώρα είστε έτοιμοι για το επόμενο μέρος! Για να κλείσετε το κέλυφος, πληκτρολογήστε αυτό: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/el/django_start_project/README.md b/el/django_start_project/README.md new file mode 100644 index 00000000000..5717d039951 --- /dev/null +++ b/el/django_start_project/README.md @@ -0,0 +1,202 @@ +# Το πρώτο σας έργο Django! + +> Μέρος αυτού του κεφαλαίου είναι βασισμένο στα σεμινάρια από τα Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +Πρόκειται να δημιουργήσουμε ένα μικρό blog! + +Το πρώτο βήμα είναι να ξεκινήσουμε ένα νέο έργο Django. Βασικά, αυτό σημαίνει ότι θα εκτελέσουμε μερικά σενάρια που παρέχονται από το Django τα οποία θα δημιουργήσουν τον σκελετό ενός πρότζεκτ Django για εμάς. Αυτά είναι ένα μάτσο καταλόγων και αρχείων που θα χρησιμοποιήσουμε αργότερα. + +Τα ονόματα μερικών αρχείων και καταλόγων είναι πολύ σημαντικά για το Django. Δεν πρέπει να μετονομάσετε τα αρχεία που πρόκειται να δημιουργήσουμε. Μετακινώντας τα σε ένα διαφορετικό μέρος δεν είναι επίσης καλή ιδέα. Το Django χρειάζεται να διατηρήσει μία συγκεκριμένη δομή για να μπορεί να βρει σημαντικά πράγματα. + +> Θυμηθείτε να εκτελέσετε τα πα΄ντα στο εικονικό περιβάλλον. Εάν δεν δείτε ένα πρόθημα `(περιβάλλον)` στην κονσόλα σας, θα πρέπει να ενεργοποιήσετε το εικονικό περιβάλλον σας. Εξηγήσαμε πως να το κάνετε αυτό στο κεφάλαιο **Εγκατάσταση Django** στο κομμάτι **Δουλεύοντας με το εικονικό περιβάλλον**. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +Στην κονσόλα σας Mac OS X ή Linux, πρέπει να εκτελέσετε την ακόλουθη εντολή. ** Μην ξεχάσετε να προσθέσετε την περίοδο (ή τελεία)`. ` στο τέλος!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> Η τελεία `.` είναι ζωτικής σημασίας επειδή λέει στο σενάριο να εγκαταστήσει το Django στο τρέχον κατάλογο σας ( για το οποίο η τελεία `.` είναι μία βραχυπρόθεσμη αναφορά). +> +> **Σημείωση** Όταν πληκτρολογείτε την παραπάνω εντολή, θυμηθείτε ότι πληκτρολογείτε το κομμάτι που ξεκινά με `διαχειριστής-django`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +Στα Windows πρέπει να εκτελέσετε την ακόλουθη εντολή. **(Μην ξεχάσετε να προσθέσετε την περίοδο (ή τελεία)`.` στο τέλος)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`διαχειριστής-django.py` είναι ένα σενάριο που θα δημιουργήσει τους καταλόγους και τα αρχεία για εσάς, Θα πρέπει τώρα να έχετε μια δομή καταλόγου που μοιάζει κάπως έτσι: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **Σημείωση**: Στην δομή καταλόγου σας, θα δείτε επίσης τον κατάλογο σας `εικονικό περιβάλλον` που δημιουργήσαμε προηγουμένως. + +`διαχείριση.py` είναι ένα σενάριο που βοηθά με την διαχείριση της σελίδας. Με αυτό θα μπορούμε να (μεταξύ άλλων πραγμάτων) ξεκινήσουμε ένα διακομιστή ιστού στον υπολογιστή μας χωρίς να εγκαταστήσουμε οτιδήποτε άλλο. + +Το αρχείο `ρυθμίσεις.py` περιέχει την διαμόρφωση παραμέτρων της ιστοσελίδας σας. + +Θυμάστε όταν μιλήσαμε σχετικά με ένα μεταφορέα αλληλογραφίας που ελέγχει που να παραδώσει ένα γράμμα; Το αρχείο `urls.py` περιέχει μία λίστα από σχέδια που χρησιμοποιούνται από το `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Σημείωση**: Αν χρησιμοποιείτε ένα Chromebook, προσθέστε αυτή τη γραμμή στο τέλος του αρχείου σας settings.py: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Δημιουργία μιας βάσης δεδομένων + +Υπάρχουν πολλά διαφορετικά λογισμικά βάσης δεδομένων που μπορούν να αποθηκεύσουν δεδομένα για την σελίδα σας. Θα χρησιμοποιήσουμε το προεπιλεγμένο, `sqlite3`. + +Αυτό έχει ήδη εγκατασταθεί σε αυτό το τμήμα του αρχείου σας `mysite/settings.py`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +Για να δημιουργήσετε μία βάση δεδομένων για το blog μας, ας εκτελέσουμε το ακόλουθο στην κονσόλα: `python manage.py migrate` ( χρειάζεται να είμαστε στον κατάλογο `djangogirls` που περιέχει το αρχείο `manage.py`). Αν αυτό πάει καλά, θα πρέπει να δείτε κάτι σαν αυτό: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +Και τελειώσαμε! Ώρα να ξεκινήσουμε τον διακομιστή ιστού και να δούμε εάν η ιστοσελίδα μας λειτουργεί! + +## Εκκίνηση του διακομιστή ιστού + +Θα πρέπει να είστε στον κατάλογο που περιέχει το αρχείο `manage.py` ( στον κατάλογο `djangogirls`). Στην κονσόλα, μπορούμε να ξεκινήσουμε τον διακομιστή ιστού εκτελώντας `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Εάν είστε σε ένα Chromebook, χρησιμοποιείστε αυτή την εντολή: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +Αν είστε σε Windows και αυτή η ενέργεια αποτύχει με το `UnicodeDecodeError`, χρησιμοποιείστε αντί για αυτό, αυτή την εντολή: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![It worked!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/el/django_templates/README.md b/el/django_templates/README.md new file mode 100644 index 00000000000..688d2245260 --- /dev/null +++ b/el/django_templates/README.md @@ -0,0 +1,106 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Σχήμα 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Σχήμα 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Σχήμα 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Σχήμα 13.4](images/donut.png) \ No newline at end of file diff --git a/el/django_urls/README.md b/el/django_urls/README.md new file mode 100644 index 00000000000..c491b27de5c --- /dev/null +++ b/el/django_urls/README.md @@ -0,0 +1,129 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![Url](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Regex + +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. + +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: + +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern + +Anything else in the URL definition will be taken literally. + +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. + +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: + +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/el/django_views/README.md b/el/django_views/README.md new file mode 100644 index 00000000000..07afe091a52 --- /dev/null +++ b/el/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/el/dynamic_data_in_templates/README.md b/el/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..807bb666ebc --- /dev/null +++ b/el/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/el/extend_your_application/README.md b/el/extend_your_application/README.md new file mode 100644 index 00000000000..0bae760be7c --- /dev/null +++ b/el/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: + +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? Of course: adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`. + +It will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ 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 %} + +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 --all . + $ git status + $ 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/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/el/how_the_internet_works/README.md b/el/how_the_internet_works/README.md new file mode 100644 index 00000000000..76af208ee6a --- /dev/null +++ b/el/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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. + +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +OK, but you want to know how the Internet looks, right? + +We drew you a picture! It looks like this: + +![Σχήμα 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: + +![Σχήμα 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 https://djangogirls.org is saved) we need to pass a request through many, many different machines. + +It looks like this: + +![Σχήμα 1.3](images/internet_2.png) + +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. + +![Σχήμα 1.4](images/internet_4.png) + +That's how it works - 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 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, 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 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! \ No newline at end of file diff --git a/el/html/README.md b/el/html/README.md new file mode 100644 index 00000000000..538a404ee9d --- /dev/null +++ b/el/html/README.md @@ -0,0 +1,213 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Σχήμα 11.1](images/step1.png) + +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Add the following to your template file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +

Hi there!

+

It works!

+ +``` + +So how does your website look now? Visit it to find out: http://127.0.0.1:8000/ + +![Σχήμα 11.2](images/step3.png) + +It worked! Nice work there :) + +* 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Σχήμα 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `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, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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.

+
+ + +``` + +We've created three `div` sections here. + +* 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: + +![Σχήμα 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to Github + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% 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: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **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): + +{% 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. + +{% 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: + +{% 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 + $ git pull + [...] + + +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. + +* 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. :) \ No newline at end of file diff --git a/el/install_git.md b/el/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/el/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/el/installation/README.md b/el/installation/README.md new file mode 100644 index 00000000000..23cc9661962 --- /dev/null +++ b/el/installation/README.md @@ -0,0 +1,58 @@ +# 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 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) + +* [Εισαγωγή στην Python](../python_introduction/README.md) + +* [Τι είναι το 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. \ No newline at end of file diff --git a/el/instructions.md b/el/instructions.md new file mode 100644 index 00000000000..d042926b29a --- /dev/null +++ b/el/instructions.md @@ -0,0 +1,60 @@ +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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/el/intro_to_command_line/README.md b/el/intro_to_command_line/README.md new file mode 100644 index 00000000000..ff8927b678c --- /dev/null +++ b/el/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +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. :) + +> 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 by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Έγινε! Για να βεβαιωθείς οτι έχει διαγραφεί, ας το ελέγξουμε: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### $ rm -r practice + +Αυτά για τώρα! Μπορείς να κλείσεις τη γραμμή εντολών με ασφάλεια τώρα. Ας το κάνουμε με τον τρόπο του χάκερ, εντάξει? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Ωραίο, ε? :) + +## Περίληψη + +Μια περίληψη κάποιων χρήσιμων εντολών: + +| Εντολή (Windows) | Εντολή (Mac OS / Linux) | Περιγραφή | Παράδειγμα | +| ---------------- | ----------------------- | ----------------------------- | ------------------------------------------------- | +| exit | exit | κλείσιμο παραθύρου | **exit** | +| cd | cd | αλλάξτε κατάλογο | **cd test** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| dir | ls | λίστα καταλόγων/αρχείων | **dir** | +| copy | cp | αντιγραφή αρχείου | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | move file | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | δημιούργησε έναν νέο κατάλογο | **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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Είστε έτοιμη; + +Let's dive into Python! \ No newline at end of file diff --git a/el/python_installation/README.md b/el/python_installation/README.md new file mode 100644 index 00000000000..93f81cb42d9 --- /dev/null +++ b/el/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/el/python_installation/instructions.md b/el/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/el/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/el/python_introduction/README.md b/el/python_introduction/README.md new file mode 100644 index 00000000000..010f97ff08b --- /dev/null +++ b/el/python_introduction/README.md @@ -0,0 +1,1062 @@ +# Εισαγωγή στην Python + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Ας γράψουμε λίγο κώδικα! + +## Παράθυρο εντολών Python + +> 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. + +Για να αρχίσεις να παίζεις με την Python, πρέπει να ανοίξεις μια *γραμμή εντολών* στον υπολογιστή σου. You should already know how to do that – you learned it in the [Intro to Command Line](../intro_to_command_line/README.md) chapter. + +Μόλις είσαι έτοιμη, ακολούθησε τις παρακάτω οδηγίες. + +Θέλουμε να ανοίξουμε μια κονσόλα Python, έτσι πληκτρολόγησε `python` σε Windows ή `python3` σε Mac OS/Linux και πατήστε `enter`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.1 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Η πρώτη σου Python εντολή! + +Αφού εκτέλεσες την εντολή Python, το παράθυρο εντολών άλλαξε σε `>>>`. Για εμάς αυτό σημαίνει ότι τώρα μπορούμε να χρησιμοποιούμε μόνο εντολές για τη γλώσσα Python. You don't have to type in `>>>` – Python will do that for you. + +Εάν θέλεις να τερματίσεις την κονσόλα Python σε οποιοδήποτε σημείο, απλά πληκτρολόγησε `exit()` ή `Ctrl + Z` για Windows και `Ctrl + D` για το Mac/Linux. Τότε δεν θα μπορείς να δείς το `>>>` πια. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +Διασκέδασε με αυτό για λίγο και στη συνέχεια έλα πίσω εδώ. :) + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, simply type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Περίληψη + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% 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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% 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! + +{% 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% 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 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 learned another amazing thing. + +### Περίληψη + +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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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 + +{% 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!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Περίληψη + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 by that we mean it includes the first value, but not the last. + +## Περίληψη + +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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/el/signup_pythonanywhere.md b/el/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/el/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/el/template_extending/README.md b/el/template_extending/README.md new file mode 100644 index 00000000000..ca905372bc5 --- /dev/null +++ b/el/template_extending/README.md @@ -0,0 +1,147 @@ +# Template extending + +Ένα άλλο ωραίο πράγμα που προσφέρει το Django είναι η **επέκταση των templates**. Τι σημαίνει αυτό; Αυτό σημαίνει ότι μπορείς να χρησιμοποιήσεις τα ίδια κομμάτια HTML για διαφορετικές σελίδες του διαδυκτιακού σου τόπου. + +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 a base template + +Το base template είναι το πιο βασικό template που μπορείς να επεκτείνεις σε κάθε σελίδα του ιστιότοπού σου. + +Ας δημιουργήσουμε ένα αρχείο `base.html` μεσα στο `blog/templates/blog/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +Στη συνέχεια, άνοιξε το και να αντίγραψε τα πάντα από `post_list.html` στο `base.html`, έτσι: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Στη συνέχεια στο `base.html`, αντικατάστησε τα περιεχόμενα ``(τα πάντα μεταξύ ``και ``) με αυτό: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). Θα σου δείξουμε πως να το κάνεις αυτο σε μια στιγμή. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Έτσι:{% 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' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Αυτό είναι! Έλεγξε εάν η ιστοσελίδα σου εξακολουθεί να λειτουργεί σωστά. :) + +> 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. \ No newline at end of file diff --git a/el/whats_next/README.md b/el/whats_next/README.md new file mode 100644 index 00000000000..91c16a4bb0d --- /dev/null +++ b/el/whats_next/README.md @@ -0,0 +1,25 @@ +# What's next? + +Να συγχαρείς τον εαυτό σου! **Είσαι φοβερή**. Είμαστε περήφανοι! <3 + +### Τι μπορείς να κάνεις τώρα; + +Κάνε ένα διάλειμμα και χαλάρωσε. Μόλις έχεις κάνει κάτι πραγματικά τεράστιο. + +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](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). + +Later on, you can try the resources listed below. They're all very recommended! + +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/en/README.md b/en/README.md index d639cc1e3d5..147df99bf89 100644 --- a/en/README.md +++ b/en/README.md @@ -5,9 +5,9 @@ > To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/4.0/ ## Welcome -Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. +Welcome to the Django Girls Tutorial! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. -As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) ## Introduction @@ -21,7 +21,7 @@ We hope that we'll be able to make you love technology as much as we do! ## What will you learn during the tutorial? -Once you've finished the tutorial, you will have a simple, working web application: your own blog. We will show you how to put it online, so others will see your work! +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! It will (more or less) look like this: @@ -33,7 +33,7 @@ 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. +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. @@ -42,10 +42,10 @@ In every chapter already covered, there is a link that points to the correct vid 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? +## Would you like to help us translate the tutorial into other languages? 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 us of the language so we can add it. +If your language is not listed on [crowdin](https://crowdin.com/), 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 ffa1b240450..59e8d01d2ae 100644 --- a/en/SUMMARY.md +++ b/en/SUMMARY.md @@ -2,6 +2,14 @@ * [Introduction](README.md) * [Installation](installation/README.md) + * [Command Line](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Code Editor](installation/README.md#code-editor) + * [Virtual Environment](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github) + * [PythonAnywhere](installation/README.md#pythonanywhere) * [Installation (chromebook)](chromebook_setup/README.md) * [How the Internet works](how_the_internet_works/README.md) * [Introduction to command line](intro_to_command_line/README.md) @@ -14,7 +22,7 @@ * [Django models](django_models/README.md) * [Django admin](django_admin/README.md) * [Deploy!](deploy/README.md) -* [Django urls](django_urls/README.md) +* [Django URLs](django_urls/README.md) * [Django views – time to create!](django_views/README.md) * [Introduction to HTML](html/README.md) * [Django ORM (Querysets)](django_orm/README.md) diff --git a/en/chromebook_setup/README.md b/en/chromebook_setup/README.md index a4843977603..cadeff050a0 100644 --- a/en/chromebook_setup/README.md +++ b/en/chromebook_setup/README.md @@ -1,5 +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). +> **Note** If you already worked through the [installation steps](../installation/README.md), 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 +{% include "/chromebook_setup/instructions.md" %} diff --git a/en/chromebook_setup/instructions.md b/en/chromebook_setup/instructions.md index d7c8e4384c8..973e368c6a0 100644 --- a/en/chromebook_setup/instructions.md +++ b/en/chromebook_setup/instructions.md @@ -2,67 +2,173 @@ You can [skip right over this section](http://tutorial.djangogirls.org/en/instal are, your installation experience will be a little different. You can ignore the rest of the installation instructions. -### Cloud 9 +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) -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 +Cloud IDE 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 the software. For the duration +of the tutorial, cloud IDE 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. +somewhere else that cloud IDE sets up for you. +Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). +You can choose one of the cloud IDEs, and follow the instruction of the cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Go to [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Sign up for an account +3. Click _New Server_ and choose the Django app +4. Click Terminal button(on the left side of the window) + +Now you should see an interface with a sidebar, buttons at the left. +Click "Terminal" button to open terminal window with prompt like this: + +{% filename %}Terminal{% endfilename %} +``` +$ +``` + +The terminal on the PaizaCloud Cloud IDE is prepared for your instructions. +You can resize or maximize that window to make it a bit bigger. + +#### AWS Cloud9 +Currently Cloud 9 requires you to sign up with AWS and enter credit card +information. 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) +2. Go to [c9.io](https://c9.io) and click _Get started with AWS Cloud9_ +3. Sign up for an AWS account (requires credit card information, but you can + use it for free) +4. In the AWS Dashboard, enter _Cloud9_ in the search bar and click it +5. In the Cloud 9 dashboard, click _Create environment_ +6. Name it _django-girls_ +7. While configuring settings, select _Create a new instance for environment + (EC2)_ for "Environment Type" and the _t2.micro_ "Instance type" (it should + say "Free-tier eligible."). The default cost-saving setting is fine and you + can keep the other defaults. +8. Click _Next step_ +9. Click _Create environment_ 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 %} +{% filename %}bash{% 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 +This bottom area is your terminal. You can use the terminal to send instructions +to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. -### Virtual Environment +#### Glitch.com Cloud IDE -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. +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click _New Project_ and choose _hello-webpage_ +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: -In your terminal at the bottom of the Cloud 9 interface, run the following: +{% filename %}Terminal{% endfilename %} +``` +app@name-of-your-glitch-project:~ +``` -{% filename %}Cloud 9{% endfilename %} +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. +Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} ``` -sudo apt update -sudo apt install python3.6-venv +Django~={{ book.django_version }} ``` -If this still doesn't work, ask your coach for some help. +{% filename %}.bash_profile{% endfilename %} +```bash +alias python=python3 +alias pip=pip3 +``` + + +{% filename %}start.sh{% endfilename %} +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} +``` +django-admin.py startproject mysite . +refresh +``` + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. +Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. +(If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) +Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### 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. -Next, run: +Run: {% filename %}Cloud 9{% endfilename %} ``` mkdir djangogirls cd djangogirls -python3.6 -mvenv myvenv +python3 -m venv myvenv source myvenv/bin/activate -pip install django~=1.11.0 +pip install django~={{ book.django_version }} ``` -(note that on the last line we use a tilde followed by an equal sign: ~=). +(note that on the last line we use a tilde followed by an equal sign: `~=`). -### Github +### GitHub -Make a [Github](https://github.com) account. +Make a [GitHub](https://github.com) account. ### PythonAnywhere @@ -74,7 +180,7 @@ 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 +for 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 diff --git a/en/code_editor/README.md b/en/code_editor/README.md index e9f908b2936..c1ff8c58248 100644 --- a/en/code_editor/README.md +++ b/en/code_editor/README.md @@ -4,8 +4,8 @@ You're about to write your first line of code, so it's time to download a code editor! -> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. The cloud IDE you chose (PaizaCloud Cloud IDE or AWS Cloud9) includes a code editor, and when you open a file in your IDE from the File menu, you will automatically be using the editor. -> **Note** You might have done this earlier in the Installation chapter – if so, you can skip right ahead to the next chapter! +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – 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 index f00c716f82f..4255dfc4754 100644 --- a/en/code_editor/instructions.md +++ b/en/code_editor/instructions.md @@ -2,6 +2,12 @@ There are a lot of different editors and it largely boils down to personal prefe Our suggestions are below, but feel free to ask your coach what their preferences are – it'll be easier to get help from them. +## Visual Studio Code + +Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + +[Download it here](https://code.visualstudio.com/) + ## Gedit Gedit is an open-source, free editor, available for all operating systems. @@ -10,14 +16,14 @@ Gedit is an open-source, free editor, available for all operating systems. ## 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. +Sublime Text is a very popular editor with a free evaluation period 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. +Atom is another popular editor. It's free, open-source and available for Windows, OS X and Linux. Atom is developed by [GitHub](https://github.com/). [Download it here](https://atom.io/) diff --git a/en/css/README.md b/en/css/README.md index 9a0051f2ca6..5a89a14b4c2 100644 --- a/en/css/README.md +++ b/en/css/README.md @@ -16,15 +16,14 @@ It was written by programmers who worked for Twitter. Now it's developed by volu ## Install Bootstrap -To install Bootstrap, you need to add this to your `` in your `.html` file: +To install Bootstrap, open up your `.html` file in the code editor and add this to the `` section: {% 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. So go ahead, open your website and refresh the page. Here it is! ![Figure 14.1](images/bootstrap1.png) @@ -38,7 +37,7 @@ Finally we will take a closer look at these things we've been calling __static f ### Where to put static files for Django -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 need to add some static files for our own app, `blog`. We do that by creating a folder called `static` inside the blog app: @@ -46,7 +45,8 @@ We do that by creating a folder called `static` inside the blog app: djangogirls ├── blog │ ├── migrations -│ └── static +│ ├── static +│   └── templates └── mysite ``` @@ -67,24 +67,25 @@ djangogirls 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. 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. +We won't be going too deep into customizing and learning about CSS here. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. -But let's do at least a little. Maybe we could change the color of our header? +But let's do at least a little. Maybe we could change the color of our headers? 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, h2 a { + color: #C25100; } + ``` -`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! +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element; the `h2 a` selector does the same thing for `h2` elements. 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 `#C25100`, which is a dark orange. Or you can put your own color here, but make sure it has good contrast against a white background! 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`: +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 element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: ```html @@ -92,11 +93,11 @@ We also identify elements by the attribute `class` or the attribute `id`. Class You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). -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: +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file in the code editor and add this line at the very beginning of it: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html -{% load staticfiles %} +{% load static %} ``` We're just loading static files here. :) @@ -106,32 +107,32 @@ Between the `` and `` tags, after the links to the Bootstrap CSS fi ```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. +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 be overriden by 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 %} +{% load static %} + Django Girls blog - - + - + {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

+
+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %} @@ -167,8 +168,8 @@ Find the `h1 a` declaration block (the code between braces `{` and `}`) in the C {% filename %}blog/static/css/blog.css{% endfilename %} ```css -h1 a { - color: #FCA205; +h1 a, h2 a { + color: #C25100; font-family: 'Lobster'; } ``` @@ -180,47 +181,52 @@ Great! 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: +Go ahead and name some parts of the HTML code. Replace the `header` that contains your header with the following: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - + ``` -And now add a class `post` to your `div` containing a blog post. +And now add a class `post` to your `article` containing a blog post. {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html -
-

published: {{ post.published_date }}

-

{{ post.title }}

+
+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ ``` -We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, copy and paste it into your `blog/static/css/blog.css` file: {% filename %}blog/static/css/blog.css{% endfilename %} ```css .page-header { - background-color: #ff9400; + background-color: #C25100; margin-top: 0; + margin-bottom: 40px; padding: 20px 20px 20px 40px; } -.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { +.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 { +h1, +h2, +h3, +h4 { font-family: 'Lobster', cursive; } @@ -232,11 +238,14 @@ h1, h2, h3, h4 { float: right; } -.post-form textarea, .post-form input { +.post-form textarea, +.post-form input { width: 100%; } -.top-menu, .top-menu:hover, .top-menu:visited { +.top-menu, +.top-menu:hover, +.top-menu:visited { color: #ffffff; float: right; font-size: 26pt; @@ -247,9 +256,27 @@ h1, h2, h3, h4 { margin-bottom: 70px; } -.post h1 a, .post h1 a:visited { +.post h2 a, +.post h2 a:visited { color: #000000; } + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} ``` Then surround the HTML code which displays the posts with declarations of classes. Replace this: @@ -257,11 +284,11 @@ Then surround the HTML code which displays the posts with declarations of classe {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

+
+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %} ``` @@ -269,21 +296,21 @@ in the `blog/templates/blog/post_list.html` with this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html -
+
-
+
{% for post in posts %} -
-
-

published: {{ post.published_date }}

-
-

{{ post.title }}

+
+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %}
-
+
``` Save those files and refresh your website. @@ -295,7 +322,6 @@ Look at the code we just pasted to find the places where we added classes in the Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! -We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. Ready for the next chapter?! :) - diff --git a/en/deploy/README.md b/en/deploy/README.md index 202528bd62c..c6c4c6dde4d 100644 --- a/en/deploy/README.md +++ b/en/deploy/README.md @@ -4,7 +4,7 @@ Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) -As you learned, a website has to be located on a server. There are a lot of server providers available on the internet. We will use one that has a relatively simple deployment process: [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! @@ -12,7 +12,7 @@ These three places will be important to you. Your local computer will be the pl # Git -> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. {% include "/deploy/install_git.md" %} @@ -36,20 +36,48 @@ Git will track changes to all the files and folders in this directory, but there {% filename %}.gitignore{% endfilename %} ``` +# Python *.pyc *~ __pycache__ -myvenv + +# Env +.env +myvenv/ +venv/ + +# Database db.sqlite3 -/static + +# Static folder at project root +/static/ + +# macOS +._* .DS_Store +.fseventsd +.Spotlight-V100 + +# Windows +Thumbs.db* +ehthumbs*.db +[Dd]esktop.ini +$RECYCLE.BIN/ + +# Visual Studio +.vscode/ +.history/ +*.code-workspace ``` And save it as `.gitignore` in the "djangogirls" folder. -> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. +Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden +and the normal `ls` command won't show these files. +Instead use `ls -a` to see the `.gitignore` file. -> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: @@ -58,7 +86,7 @@ It's a good idea to use a `git status` command before `git add` or whenever you $ git status On branch master -Initial commit +No commits yet Untracked files: (use "git add ..." to include in what will be committed) @@ -67,6 +95,7 @@ Untracked files: blog/ manage.py mysite/ + requirements.txt nothing added to commit but untracked files present (use "git add" to track) ``` @@ -75,33 +104,33 @@ And finally we save our changes. Go to your console and run these commands: {% filename %}command-line{% endfilename %} ``` -$ git add --all . +$ git add . $ git commit -m "My Django Girls app, first commit" [...] 13 files changed, 200 insertions(+) create mode 100644 .gitignore [...] create mode 100644 mysite/wsgi.py - ``` +``` ## Pushing your code to GitHub -Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. - +![](images/new_github_repo.png) -> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. -On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: - +![](images/github_get_repo_url_screenshot.png) Now we need to hook up the Git repository on your computer to the one up on GitHub. -Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): {% filename %}command-line{% endfilename %} ``` @@ -109,16 +138,14 @@ $ git remote add origin https://github.com//my-first-blog. $ git push -u origin master ``` -Enter your GitHub username and password and you should see something like this: +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: {% filename %}command-line{% endfilename %} ``` -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 +To https://github.com/ola/my-first-blog.git * [new branch] master -> master Branch master set up to track remote branch master from origin. ``` @@ -130,168 +157,102 @@ Your code is now on GitHub. Go and check it out! You'll find it's in fine compa # Setting up our blog on PythonAnywhere +## Sign up for a PythonAnywhere account + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. {% include "/deploy/signup_pythonanywhere.md" %} -## Pulling our code down on PythonAnywhere +## Configuring our site on PythonAnywhere -When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. -pointing at Other: Bash in Start a new Console +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. -Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``): +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: {% filename %}PythonAnywhere command-line{% endfilename %} ``` -$ git clone https://github.com//my-first-blog.git +$ pip3.8 install --user pythonanywhere ``` -This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): {% filename %}PythonAnywhere command-line{% endfilename %} ``` -$ 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 +$ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git ``` +As you watch that running, you'll be able to see what it's doing: -### Creating a virtualenv on PythonAnywhere +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API -Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: {% filename %}PythonAnywhere command-line{% endfilename %} ``` -$ cd my-first-blog - -$ virtualenv --python=python3.6 myvenv -Running virtualenv with interpreter /usr/bin/python3.6 -[...] -Installing setuptools, pip...done. - -$ source myvenv/bin/activate - -(myvenv) $ pip install django~=1.11.0 -Collecting django -[...] -Successfully installed django-1.11.3 +(ola.pythonanywhere.com) $ python manage.py createsuperuser ``` +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. -> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. - - - -### Creating the database on PythonAnywhere - -Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. - -Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: {% filename %}PythonAnywhere command-line{% endfilename %} ``` -(mvenv) $ python manage.py migrate -Operations to perform: -[...] - Applying sessions.0001_initial... OK -(mvenv) $ python manage.py createsuperuser +(ola.pythonanywhere.com) $ ls +blog db.sqlite3 manage.py mysite requirements.txt static +(ola.pythonanywhere.com) $ ls blog/ +__init__.py __pycache__ admin.py apps.py migrations models.py +tests.py views.py ``` -## Publishing our blog as a web app - -Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! - -Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) -After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. - -> **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) - - -### Setting the virtualenv - -You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. - - - -In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home//my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. - -> **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. - - -### Configuring the WSGI file - -Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. - -Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. - -Delete all the contents and replace them with the following: - -{% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} -```python -import os -import sys - -path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler -application = StaticFilesHandler(get_wsgi_application()) -``` -This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. +## You are now live! -The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) -Hit **Save** and then go back to the **Web** tab. -We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. ## Debugging tips -If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: -- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: -- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. -- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? -- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. -There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). And remember, your coach is here to help! -# You are live! +# Check out your site! -The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? -Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! diff --git a/en/deploy/install_git.md b/en/deploy/install_git.md index 211407c2775..0208d483d93 100644 --- a/en/deploy/install_git.md +++ b/en/deploy/install_git.md @@ -1,19 +1,19 @@ -Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in word processor programs (e.g., Microsoft Word or LibreOffice Writer), but much more powerful. ## Installing Git -You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for two: in the step where it asks to choose your editor, you should pick Nano, and in the step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. -Do not forget to restart the command prompt or powershell after the installation finished successfully. +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. -Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. > **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) @@ -24,7 +24,7 @@ data-collapse=true ces--> {% filename %}command-line{% endfilename %} ```bash -$ sudo apt-get install git +$ sudo apt install git ``` diff --git a/en/deploy/signup_pythonanywhere.md b/en/deploy/signup_pythonanywhere.md index 1c45f14224b..f4eefc3bf7c 100644 --- a/en/deploy/signup_pythonanywhere.md +++ b/en/deploy/signup_pythonanywhere.md @@ -1,7 +1,21 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use +it for hosting our site, live and on the Internet. -Next it's time to sign up for a free "Beginner" account on PythonAnywhere. +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). * [www.pythonanywhere.com](https://www.pythonanywhere.com/) +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) -> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) diff --git a/en/django/README.md b/en/django/README.md index f57843e8c97..acb6a9f2358 100644 --- a/en/django/README.md +++ b/en/django/README.md @@ -22,6 +22,6 @@ Imagine a mail carrier with a letter. She is walking down the street and checks In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. -Of course, the description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. -So instead of diving too much into details, we will simply start creating something with Django and we will learn all the important parts along the way! +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! diff --git a/en/django_admin/README.md b/en/django_admin/README.md index 5aa41f3a5e7..c6ae54059d9 100644 --- a/en/django_admin/README.md +++ b/en/django_admin/README.md @@ -2,7 +2,7 @@ To add, edit and delete the posts we've just modeled, we will use Django admin. -Let's open the `blog/admin.py` file and replace its contents with this: +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: {% filename %}blog/admin.py{% endfilename %} ```python @@ -22,13 +22,21 @@ To log in, you need to create a *superuser* - a user account that has control ov > Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the Your first Django project! chapter, in the Starting the web server section. -When prompted, type your username (lowercase, no spaces), email address, and password. Don't worry that you can't see the password you're typing in – that's how it's supposed to be. Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): - -{% filename %}command-line{% endfilename %} +{% filename %}Mac OS X or Linux:{% endfilename %} ``` (myvenv) ~/djangogirls$ python manage.py createsuperuser -Username: admin -Email address: admin@admin.com +``` + +{% filename %}Windows:{% endfilename %} +``` +(myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser +``` + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + +``` +Username: ola +Email address: ola@example.com Password: Password (again): Superuser created successfully. @@ -38,12 +46,12 @@ Return to your browser. Log in with the superuser's credentials you chose; you s ![Django admin](images/django_admin3.png) -Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. ![Django admin](images/edit_post3.png) -If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! diff --git a/en/django_forms/README.md b/en/django_forms/README.md index d6d6693cf6a..fee437dc6b1 100644 --- a/en/django_forms/README.md +++ b/en/django_forms/README.md @@ -15,7 +15,7 @@ blog └── forms.py ``` -OK, let's open it and type the following code: +OK, let's open it in the code editor and type the following code: {% filename %}blog/forms.py{% endfilename %} ```python @@ -30,7 +30,7 @@ class PostForm(forms.ModelForm): fields = ('title', 'text',) ``` -We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). `PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. @@ -44,67 +44,79 @@ So once again we will create a link to the page, a URL, a view and a template. ## Link to a page with the form -It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: {% filename %}blog/templates/blog/base.html{% endfilename %} ```html - + + {% include './icons/file-earmark-plus.svg' %} + ``` -Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` -After adding the line, your HTML file should now look like this: +After editing the line, your HTML file should now look like this: {% filename %}blog/templates/blog/base.html{% endfilename %} ```html -{% load staticfiles %} +{% load static %} + Django Girls blog - - + - -
+ +
-
+
{% block content %} {% endblock %}
-
+
``` -After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! ## URL -We open `blog/urls.py` and add a line: +We open `blog/urls.py` in the code editor and add a line: {% filename %}blog/urls.py{% endfilename %} ```python -url(r'^post/new/$', views.post_new, name='post_new'), +path('post/new/', views.post_new, name='post_new'), ``` And the final code will look like this: {% filename %}blog/urls.py{% endfilename %} ```python -from django.conf.urls import url +from django.urls import path from . import views urlpatterns = [ - url(r'^$', views.post_list, name='post_list'), - url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), - url(r'^post/new/$', views.post_new, name='post_new'), + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), ] ``` @@ -112,7 +124,7 @@ After refreshing the site, we see an `AttributeError`, since we don't have the ` ## post_new view -Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: {% filename %}blog/views.py{% endfilename %} ```python @@ -132,10 +144,10 @@ To create a new `Post` form, we need to call `PostForm()` and pass it to the tem ## Template -We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: -- We have to display the form. We can do that with (for example) a simple {% raw %}`{{ form.as_p }}`{% endraw %}. -- The line above needs to be wrapped with an HTML form tag: `...`. +- We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +- The line above needs to be wrapped with an HTML form element: `
...
`. - We need a `Save` button. We do that with an HTML button: ``. - And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: @@ -148,7 +160,7 @@ OK, so let's see how the HTML in `post_edit.html` should look: {% extends 'blog/base.html' %} {% block content %} -

New post

+

New post

{% csrf_token %} {{ form.as_p }} @@ -168,7 +180,7 @@ The answer is: nothing. We need to do a little bit more work in our *view*. ## Saving the form -Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: {% filename %}blog/views.py{% endfilename %} ```python @@ -196,7 +208,7 @@ It's time to fill in the dots `[...]`. If `method` is `POST` then we want to con form = PostForm(request.POST) ``` -Easy! The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. We check if the form is valid and if so, we can save it! @@ -269,13 +281,19 @@ Django is taking care to validate that all the fields in our form are correct. I ## Edit form -Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. -Open `blog/templates/blog/post_detail.html` and add the line +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: {% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html - + ``` so that the template will look like this: @@ -285,29 +303,33 @@ so that the template will look like this: {% extends 'blog/base.html' %} {% block content %} -
+
+ {% endblock %} ``` -In `blog/urls.py` we add this line: +Open `blog/urls.py` in the code editor, and add this line: {% filename %}blog/urls.py{% endfilename %} ```python - url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), + path('post//edit/', views.post_edit, name='post_edit'), ``` We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. -Let's open `blog/views.py` and add this at the very end of the file: +Let's open `blog/views.py` in the code editor and add this at the very end of the file: {% filename %}blog/views.py{% endfilename %} ```python @@ -326,7 +348,7 @@ def post_edit(request, pk): return render(request, 'blog/post_edit.html', {'form': form}) ``` -This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… {% filename %}blog/views.py{% endfilename %} ```python @@ -352,25 +374,29 @@ Feel free to change the title or the text and save the changes! Congratulations! Your application is getting more and more complete! -If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ ## Security -Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. -In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: {% filename %}blog/templates/blog/base.html{% endfilename %} ```html - + + {% include './icons/file-earmark-plus.svg' %} + ``` -We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: {% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% if user.is_authenticated %} - + + {% include './icons/file-earmark-plus.svg' %} + {% endif %} ``` @@ -378,11 +404,13 @@ This `{% if %}` will cause the link to be sent to the browser only if the user r Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. -Open `blog/templates/blog/post_detail.html` and find this line: +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: {% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html - + + {% include './icons/pencil-fill.svg' %} + ``` Change it to this: @@ -390,7 +418,9 @@ Change it to this: {% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html {% if user.is_authenticated %} - + + {% include './icons/pencil-fill.svg' %} + {% endif %} ``` @@ -400,12 +430,12 @@ Since you're likely logged in, if you refresh the page, you won't see anything d Let's see if all this works on PythonAnywhere. Time for another deploy! -* First, commit your new code, and push it up to Github: +* First, commit your new code, and push it up to GitHub: {% filename %}command-line{% endfilename %} ``` $ git status -$ git add --all . +$ git add . $ git status $ git commit -m "Added views to create/edit blog post inside the site." $ git push @@ -413,14 +443,17 @@ $ git push * Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): -{% filename %}command-line{% endfilename %} +{% filename %}PythonAnywhere command-line{% endfilename %} ``` -$ cd my-first-blog +$ cd ~/.pythonanywhere.com $ git pull [...] ``` -* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. -And that should be it! Congrats :) +And that should be it. Congrats! :) diff --git a/en/django_installation/README.md b/en/django_installation/README.md index a7dd67281c8..e5e8b62d653 100644 --- a/en/django_installation/README.md +++ b/en/django_installation/README.md @@ -2,6 +2,6 @@ > **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. -> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! {% include "/django_installation/instructions.md" %} diff --git a/en/django_installation/instructions.md b/en/django_installation/instructions.md index 993b5da4165..0ec9a69cacb 100644 --- a/en/django_installation/instructions.md +++ b/en/django_installation/instructions.md @@ -12,9 +12,9 @@ Before we install Django we will get you to install an extremely useful tool to So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? -All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows it might look like `C:\Users\Name\` (where `Name` is the name of your login). +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name\` (where `Name` is the name of your login). -> __NOTE:__ On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example `C:\djangogirls`. +> __NOTE:__ On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. For this tutorial we will be using a new directory `djangogirls` from your home directory: @@ -48,7 +48,7 @@ Where `myvenv` is the name of your `virtualenv`. You can use any other name, but -Creating a `virtualenv` on both Linux and OS X is as simple as running `python3 -m venv myvenv`. +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: {% filename %}command-line{% endfilename %} @@ -56,21 +56,21 @@ It will look like this: $ python3 -m venv myvenv ``` -`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also good idea to keep the name short as you'll be referencing it a lot! +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! > __NOTE:__ On some versions of Debian/Ubuntu you may receive the following error: >{% filename %}command-line{% endfilename %} >``` >The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. -> apt-get install python3-venv +> apt install python3-venv >You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. >``` > > In this case, follow the instructions above and install the `python3-venv` package: >{% filename %}command-line{% endfilename %} >``` ->$ sudo apt-get install python3-venv +>$ sudo apt install python3-venv >``` > __NOTE:__ On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: @@ -84,8 +84,8 @@ $ python3 -m venv myvenv >{% filename %}command-line{% endfilename %} >``` ->$ sudo apt-get install python-virtualenv ->$ virtualenv --python=python3.6 myvenv +>$ sudo apt install python-virtualenv +>$ virtualenv --python=python{{ book.py_version }} myvenv >``` > __NOTE:__ If you get an error like @@ -99,7 +99,7 @@ $ python3 -m venv myvenv > >{% filename %}command-line{% endfilename %} >``` ->sudo apt install python3.6-venv +>sudo apt install python{{ book.py_version }}-venv >``` @@ -127,6 +127,15 @@ C:\Users\Name\djangogirls> myvenv\Scripts\activate > The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A >``` + + +> __NOTE:__ For users of the popular editor VS Code, which come with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +>``` +>$ . myvenv\Scripts\activate.ps1 +>``` +>The advantage is that you don't have to switch between editor windows and command-line windows + > >{% filename %}command-line{% endfilename %} >``` ->C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +>C:\Users\Name\djangogirls> python -m pip install -r requirements.txt >``` diff --git a/en/django_models/README.md b/en/django_models/README.md index 13069ed5e15..cab8f68e264 100644 --- a/en/django_models/README.md +++ b/en/django_models/README.md @@ -66,19 +66,24 @@ You can think of a model in the database as a spreadsheet with columns (fields) To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): -{% filename %}command-line{% endfilename %} +{% filename %}Mac OS X and Linux:{% endfilename %} ``` (myvenv) ~/djangogirls$ python manage.py startapp blog ``` +{% filename %}Windows:{% endfilename %} +``` +(myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog +``` + You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: ``` djangogirls ├── blog -│   ├── __init__.py │   ├── admin.py │   ├── apps.py +│   ├── __init__.py │   ├── migrations │   │   └── __init__.py │   ├── models.py @@ -86,14 +91,18 @@ djangogirls │   └── views.py ├── db.sqlite3 ├── manage.py -└── mysite - ├── __init__.py - ├── settings.py - ├── urls.py - └── wsgi.py +├── mysite +│   ├── __init__.py +│   ├── settings.py +│   ├── urls.py +│   └── wsgi.py +├── myvenv +│   └── ... +└── requirements.txt + ``` -After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: {% filename %}mysite/settings.py{% endfilename %} ```python @@ -104,7 +113,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'blog', + 'blog.apps.BlogConfig', ] ``` @@ -112,22 +121,21 @@ INSTALLED_APPS = [ In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. -Let's open `blog/models.py`, remove everything from it, and write code like this: +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: {% filename %}blog/models.py{% endfilename %} ```python +from django.conf import settings from django.db import models from django.utils import timezone class Post(models.Model): - author = models.ForeignKey('auth.User') + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) title = models.CharField(max_length=200) text = models.TextField() - created_date = models.DateTimeField( - default=timezone.now) - published_date = models.DateTimeField( - blank=True, null=True) + created_date = models.DateTimeField(default=timezone.now) + published_date = models.DateTimeField(blank=True, null=True) def publish(self): self.published_date = timezone.now() @@ -155,7 +163,7 @@ Now we define the properties we were talking about: `title`, `text`, `created_da - `models.DateTimeField` – this is a date and time. - `models.ForeignKey` – this is a link to another model. -We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. @@ -187,7 +195,6 @@ Django prepared a migration file for us that we now have to apply to our databas Operations to perform: Apply all migrations: blog Running migrations: - Rendering model states... DONE Applying blog.0001_initial... OK ``` diff --git a/en/django_orm/README.md b/en/django_orm/README.md index ff8118e2506..54ec2a1d2ae 100644 --- a/en/django_orm/README.md +++ b/en/django_orm/README.md @@ -27,7 +27,7 @@ The effect should be like this: >>> ``` -You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. ### All objects @@ -49,7 +49,7 @@ Oops! An error showed up. It tells us that there is no Post. It's correct – we >>> from blog.models import Post ``` -This is simple: we import the model `Post` from `blog.models`. Let's try displaying all posts again: +We import the model `Post` from `blog.models`. Let's try displaying all posts again: {% filename %}command-line{% endfilename %} ```python @@ -86,20 +86,21 @@ What users do we have in our database? Try this: ]> ``` -This is the superuser we created earlier! Let's get an instance of the user now: +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): {% filename %}command-line{% endfilename %} ```python >>> me = User.objects.get(username='ola') ``` -As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Now we can finally create our post: {% filename %}command-line{% endfilename %} ```python >>> Post.objects.create(author=me, title='Sample title', text='Test') + ``` Hurray! Wanna check if it worked? @@ -125,7 +126,7 @@ A big part of QuerySets is the ability to filter them. Let's say we want to find {% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(author=me) -[, , , ] +, , , ]> ``` Or maybe we want to see all the posts that contain the word 'title' in the `title` field? @@ -133,7 +134,7 @@ Or maybe we want to see all the posts that contain the word 'title' in the `titl {% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(title__contains='title') -[, ] +, ]> ``` > **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". @@ -144,7 +145,7 @@ You can also get a list of all published posts. We do this by filtering all the ```python >>> from django.utils import timezone >>> Post.objects.filter(published_date__lte=timezone.now()) -[] + ``` Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: @@ -166,7 +167,7 @@ Now try to get list of published posts again (press the up arrow key three times {% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(published_date__lte=timezone.now()) -[] +]> ``` @@ -177,7 +178,7 @@ QuerySets also allow you to order the list of objects. Let's try to order them b {% filename %}command-line{% endfilename %} ```python >>> Post.objects.order_by('created_date') -[, , , ] +, , , ]> ``` We can also reverse the ordering by adding `-` at the beginning: @@ -185,16 +186,21 @@ We can also reverse the ordering by adding `-` at the beginning: {% filename %}command-line{% endfilename %} ```python >>> Post.objects.order_by('-created_date') -[, , , ] +, , , ]> ``` -### Chaining QuerySets +### Complex queries through method-chaining -You can also combine QuerySets by **chaining** them together: +As you saw, some methods on `Post.objects` return a QuerySet. +The same methods can in turn also be called on a QuerySet, +and will then return a new QuerySet. +Thus, +you can combine their effect by **chaining** them together: -``` +```python >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> ``` This is really powerful and lets you write quite complex queries. diff --git a/en/django_start_project/README.md b/en/django_start_project/README.md index 87106f097a9..8e4a3a7fcfc 100644 --- a/en/django_start_project/README.md +++ b/en/django_start_project/README.md @@ -7,7 +7,7 @@ tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commo Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. -We're going to create a simple blog! +We're going to create a small blog! The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. @@ -42,8 +42,8 @@ On Windows you should run the following command. **(Don't forget to add the peri ``` > The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). -> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.py`. -The (myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. +The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. @@ -51,12 +51,15 @@ The (myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the ``` djangogirls -├───manage.py -└───mysite - settings.py - urls.py - wsgi.py - __init__.py +├── manage.py +├── mysite +│   ├── __init__.py +│   ├── settings.py +│   ├── urls.py +│   └── wsgi.py +├── myvenv +│   └── ... +└── requirements.txt ``` > **Note**: in your directory structure, you will also see your `venv` directory that we created before. @@ -84,9 +87,9 @@ In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choos TIME_ZONE = 'Europe/Berlin' ``` -A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). -Change the language code by changing the following line: +If you want a different language, change the language code by changing the following line: {% filename %}mysite/settings.py{% endfilename %} ```python @@ -107,13 +110,49 @@ match our hostname on PythonAnywhere once we deploy our application so we will c {% filename %}mysite/settings.py{% endfilename %} ```python -ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] ``` > **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: > `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` -> Also add `django-girls-.c9users.io` to the ALLOWED_HOSTS if you are using cloud9 +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 + +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to +> remain confidential (otherwise, anyone remixing your project could see it): +> +> * First, we are going to create a random secret key. +> Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. +> We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> * Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> * Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> * And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. +> It will correspond to the name of your project. ## Set up a database @@ -151,6 +190,8 @@ Running migrations: Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK Applying sessions.0001_initial... OK ``` @@ -170,6 +211,13 @@ If you are on a Chromebook, use this command instead: {% filename %}Cloud 9{% endfilename %} ``` (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 +``` +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} +``` +$ refresh + ``` If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: @@ -180,28 +228,32 @@ If you are on Windows and this fails with `UnicodeDecodeError`, use this command ``` -Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: {% filename %}browser{% endfilename %} ``` http://127.0.0.1:8000/ ``` -If you're using a Chromebook, you'll always visit your test server by accessing: +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: {% filename %}browser{% endfilename %} ``` -https://django-girls-.c9users.io +https://.vfs.cloud9.us-west-2.amazonaws.com +``` +or on Glitch: +``` +https://name-of-your-glitch-project.glitch.me ``` Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? -![It worked!](images/it_worked2.png) +![Install worked!](images/install_worked.png) -While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. > We reviewed how web servers work in the How the Internet works chapter. -To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). Ready for the next step? It's time to create some content! diff --git a/en/django_templates/README.md b/en/django_templates/README.md index f65a0836d81..fda0459b795 100644 --- a/en/django_templates/README.md +++ b/en/django_templates/README.md @@ -6,7 +6,7 @@ Time to display some data! Django gives us some helpful built-in __template tags You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. -__Django template tags__ allow us to transfer Python-like things into HTML, so you can build dynamic websites faster and easier. Cool! +__Django template tags__ allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! ## Display post list template @@ -19,7 +19,7 @@ To print a variable in Django templates, we use double curly brackets with the v {{ posts }} ``` -Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: ![Figure 13.1](images/step1.png) @@ -47,16 +47,16 @@ It works! But we want the posts to be displayed like the static posts we created {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html -
+ {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

+
+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %} ``` @@ -64,20 +64,20 @@ It works! But we want the posts to be displayed like the static posts we created ![Figure 13.3](images/step3.png) -Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. ## One more thing It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… -* First, push your code to Github +* First, push your code to GitHub {% filename %}command-line{% endfilename %} ``` $ git status [...] -$ git add --all . +$ git add . $ git status [...] $ git commit -m "Modified templates to display posts from database." @@ -89,15 +89,17 @@ $ git push {% filename %}PythonAnywhere command-line{% endfilename %} ``` -$ cd my-first-blog +$ cd .pythonanywhere.com $ git pull [...] ``` -* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. -Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) diff --git a/en/django_urls/README.md b/en/django_urls/README.md index 2ae25239758..25c680513fe 100644 --- a/en/django_urls/README.md +++ b/en/django_urls/README.md @@ -4,11 +4,11 @@ We're about to build our first webpage: a homepage for your blog! But first, let ## What is a URL? -A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) -![Url](images/url.png) +![URL](images/url.png) -Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. ## How do URLs work in Django? @@ -21,11 +21,11 @@ Let's open up the `mysite/urls.py` file in your code editor of choice and see wh [...] """ -from django.conf.urls import url from django.contrib import admin +from django.urls import path urlpatterns = [ - url(r'^admin/', admin.site.urls), + path('admin/', admin.site.urls), ] ``` @@ -33,37 +33,14 @@ As you can see, Django has already put something here for us. Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. -The admin URL, which you visited in previous chapter, is already here: +The admin URL, which you visited in the previous chapter, is already here: {% filename %}mysite/urls.py{% endfilename %} ```python - url(r'^admin/', admin.site.urls), + path('admin/', admin.site.urls), ``` -This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. - -## Regex - -Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. - -If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: - -* `^` for the beginning of the text -* `$` for the end of the text -* `\d` for a digit -* `+` to indicate that the previous item should be repeated at least once -* `()` to capture part of the pattern - -Anything else in the URL definition will be taken literally. - -Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. - -Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: - -* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) -* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted -* **/** tells django that another `/` character should follow -* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. ## Your first Django URL! @@ -72,48 +49,45 @@ Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home pa We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. -Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so **you will need** to add that to the import on the first line of the file. +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. Your `mysite/urls.py` file should now look like this: {% filename %}mysite/urls.py{% endfilename %} ```python -from django.conf.urls import include, url from django.contrib import admin +from django.urls import path, include urlpatterns = [ - url(r'^admin/', admin.site.urls), - url(r'', include('blog.urls')), + path('admin/', admin.site.urls), + path('', include('blog.urls')), ] ``` -Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. - -Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. - +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. ## blog.urls -Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: {% filename %}blog/urls.py{% endfilename %} ```python -from django.conf.urls import url +from django.urls import path from . import views ``` -Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) After that, we can add our first URL pattern: {% filename %}blog/urls.py{% endfilename %} ```python urlpatterns = [ - url(r'^$', views.post_list, name='post_list'), + path('', views.post_list, name='post_list'), ] ``` -As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. @@ -121,6 +95,8 @@ If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'w ![Error](images/error1.png) -Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is __no attribute 'post_list'__. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is __no attribute 'post_list'__. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. +If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + -> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ diff --git a/en/django_views/README.md b/en/django_views/README.md index 909aa5230a4..e46bb4b380c 100644 --- a/en/django_views/README.md +++ b/en/django_views/README.md @@ -8,7 +8,7 @@ Views are placed in the `views.py` file. We will add our *views* to the `blog/vi ## blog/views.py -OK, let's open up this file and see what's in there: +OK, let's open up this file in our code editor and see what's in there: {% filename %}blog/views.py{% endfilename %} ```python @@ -21,7 +21,7 @@ Not too much stuff here yet. Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. -The simplest *view* can look like this: +Let's create a *view* as the comment suggests. Add the following minimal view below it: {% filename %}blog/views.py{% endfilename %} ```python @@ -29,7 +29,7 @@ def post_list(request): return render(request, 'blog/post_list.html', {}) ``` -As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. Save the file, go to http://127.0.0.1:8000/ and see what we've got. @@ -39,4 +39,4 @@ Another error! Read what's going on now: This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! -> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ diff --git a/en/dynamic_data_in_templates/README.md b/en/dynamic_data_in_templates/README.md index 3f9a14c0bfb..d297f4ed3db 100644 --- a/en/dynamic_data_in_templates/README.md +++ b/en/dynamic_data_in_templates/README.md @@ -6,7 +6,7 @@ This is exactly what *views* are supposed to do: connect models and templates. I OK, so how will we achieve this? -We need to open our `blog/views.py`. So far `post_list` *view* looks like this: +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: {% filename %}blog/views.py{% endfilename %} ```python @@ -39,7 +39,7 @@ So now we want published blog posts sorted by `published_date`, right? We alread Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') ``` -Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: {% filename %}blog/views.py{% endfilename %} ```python @@ -52,7 +52,9 @@ def post_list(request): return render(request, 'blog/post_list.html', {}) ``` -The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. +To display our QuerySet on our blog's post list, we have two things left to do: +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. @@ -73,4 +75,4 @@ def post_list(request): That's it! Time to go back to our template and display this QuerySet! -Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ diff --git a/en/extend_your_application/README.md b/en/extend_your_application/README.md index fa54a1d3b70..ffb250bfda5 100644 --- a/en/extend_your_application/README.md +++ b/en/extend_your_application/README.md @@ -1,6 +1,8 @@ +{% set warning_icon = '' %} + # Extend your application -We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. Time to practice! @@ -10,36 +12,36 @@ We already have a `Post` model, so we don't need to add anything to `models.py`. ## Create a template link to a post's detail -We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% extends 'blog/base.html' %} {% block content %} {% for post in posts %} -
-
+
+
-

{{ post.title }}

+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %} {% endblock %} ``` -{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} -{% filename %}blog/templates/blog/post_list.html{% endfilename %} +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} ```html -

{{ post.title }}

+

{{ post.title }}

``` {% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail -And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: @@ -51,25 +53,23 @@ Let's create a URL in `urls.py` for our `post_detail` *view*! We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ -Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: -{% filename %}blog/urls.py{% endfilename %} +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} ```python -from django.conf.urls import url +from django.urls import path from . import views urlpatterns = [ - url(r'^$', views.post_list, name='post_list'), - url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), ] ``` -This part ``^post/(?P\d+)/$`` looks scary, but no worries – we will explain it for you: -- it starts with `^` again – "the beginning". -- `post/` just means that after the beginning, the URL should contain the word __post__ and a __/__. So far so good. -- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! -- `/` – then we need a __/__ again. -- `$` – "the end"! +This part ``post//`` specifies a URL pattern – we will explain it for you: +- `post/` means that the URL should begin with the word __post__ followed by a __/__. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a __/__ again before finishing the URL. That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. @@ -77,15 +77,16 @@ OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: htt ![AttributeError](images/attribute_error2.png) -Do you remember what the next step is? Of course: adding a view! +Do you remember what the next step is? It's adding a view! ## Add a post's detail view -This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + Now, we want to get one and only one blog post. To do this, we can use querysets, like this: -{% filename %}blog/views.py{% endfilename %} +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} ```python Post.objects.get(pk=pk) ``` @@ -94,7 +95,7 @@ But this code has a problem. If there is no `Post` with the given `primary key` ![DoesNotExist error](images/does_not_exist2.png) -We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. ![Page not found](images/404_2.png) @@ -104,7 +105,7 @@ OK, time to add a *view* to our `views.py` file! In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. -We should open `blog/views.py` and add the following code near the other `from` lines: +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: {% filename %}blog/views.py{% endfilename %} ```python @@ -132,30 +133,30 @@ Oh no! Another error! But we already know how to deal with it, right? We need to ## Create a template for the post details -We will create a file in `blog/templates/blog` called `post_detail.html`. +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. -It will look like this: +Enter the following code: {% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html {% extends 'blog/base.html' %} {% block content %} -
+
{% if post.published_date %} -
+
+ {% endif %} -

{{ post.title }}

+

{{ post.title }}

{{ 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 `TemplateDoesNotExist` is gone now. @@ -163,14 +164,15 @@ OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. 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. +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. {% filename %}command-line{% endfilename %} ``` $ git status -$ git add --all . +$ git add . $ git status $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." $ git push @@ -178,13 +180,31 @@ $ git push Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): -{% filename %}command-line{% endfilename %} +{% filename %}PythonAnywhere command-line{% endfilename %} ``` -$ cd my-first-blog +$ cd ~/.pythonanywhere.com $ git pull [...] ``` -Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} +``` +$ workon .pythonanywhere.com +(ola.pythonanywhere.com)$ python manage.py collectstatic +[...] +``` + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to _apply_ those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. -And that should be it! Congrats :) +And that should be it. Congrats! :) diff --git a/en/how_the_internet_works/README.md b/en/how_the_internet_works/README.md index cfcc8482452..035d6a2ddfb 100644 --- a/en/how_the_internet_works/README.md +++ b/en/how_the_internet_works/README.md @@ -6,10 +6,10 @@ 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. +The first thing you need to understand is that a website consists of 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. -If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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 @@ -25,7 +25,7 @@ Looks like a mess, right? In fact it is a network of connected machines (the abo ![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 https://djangogirls.org is saved) we need to pass a request through many, many different machines. +It is fascinating, isn't it? But 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: @@ -37,7 +37,7 @@ Your letter goes to the post office closest to you. Then it goes to another that ![Figure 1.4](images/internet_4.png) -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! +That's how it works - you send messages and you expect some response. 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 can look up the name of the person you want to contact and find their phone number and address. diff --git a/en/html/README.md b/en/html/README.md index c4deb1206e0..075f29732a9 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__). ## What is HTML? -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 is a 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__. @@ -24,25 +24,28 @@ blog └───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 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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys 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 to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. ![Figure 11.1](images/step1.png) -No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. -Add the following to your template file: +Open the new file in the code editor, and add the following: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html + +

Hi there!

It works!

+ ``` @@ -50,9 +53,10 @@ 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 :) +It worked. Nice work there! :) -- 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 `` +- The line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +- The most basic tag, ``, is always the beginning of html content 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 and body @@ -69,6 +73,7 @@ For example, you can put a web page title element inside the ``, like this {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html + Ola's blog @@ -102,43 +107,52 @@ You can now have a little fun and try to customize your template! Here are a few - `

A paragraph of text

` - `text` emphasizes your text - `text` strongly emphasizes your text -- `
` goes to another line (you can't put anything inside br) +- `
` goes to another line (you can't put anything inside br and there's no closing tag) - `link` creates a link - `
  • first item
  • second item
` makes a list, just like this one! - `
` defines a section of the page +- `` defines a set of navigation links +- `
` specifies independent, self-contained content +- `
` defines a section in a document +- `
` specifies a header for a document or section +- `
` specifies the main content of a document +- `` defines some content aside from the content it is placed in (like a sidebar) +- `
` defines a footer for a document or section +- `` defines a specific time (or datetime) Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```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.

-
+ ``` -We've created three `div` sections here. +We've created one `header` section and two `article` section here. -- 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. +- The `header` element contains the title of our blog – it's a heading and a link +- The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. It gives us this effect: @@ -152,7 +166,7 @@ What we really want to do is display real posts added in our Django admin – an It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: -### Commit, and push your code up to Github +### Commit, and push your code up to GitHub First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): @@ -161,15 +175,13 @@ First off, let's see what files have changed since we last deployed (run these c $ git status ``` -Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes within this directory: +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: {% filename %}command-line{% endfilename %} ``` -$ git add --all . +$ git add . ``` -> __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): {% filename %}command-line{% endfilename %} @@ -197,16 +209,18 @@ $ git push * 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 %} +{% filename %}PythonAnywhere command-line{% endfilename %} ``` -$ cd ~/my-first-blog +$ cd ~/.pythonanywhere.com $ git pull [...] ``` -And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). -* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. +* Finally, hop on over to the ["Web" page](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. :) diff --git a/en/installation/README.md b/en/installation/README.md index cefbd6d645f..9c9c995267a 100644 --- a/en/installation/README.md +++ b/en/installation/README.md @@ -2,36 +2,45 @@ 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. +This is because we cover installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. Good luck! +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): +- Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +- The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +- If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + # 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. +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). {% include "/chromebook_setup/instructions.md" %} -# Install Python -{% include "/python_installation/instructions.md" %} +# Brief intro to the command line {#command-line} +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: +{% include "/intro_to_command_line/open_instructions.md" %} -# Set up virtualenv and install Django -{% include "/django_installation/instructions.md" %} +# Install Python {#python} +{% include "/python_installation/instructions.md" %} -# Install a code editor +# Install a code editor {#code-editor} {% include "/code_editor/instructions.md" %} -# Install Git +# Set up virtualenv and install Django {#virtualenv} +{% include "/django_installation/instructions.md" %} + +# Install Git {#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 GitHub account {#github} +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). -# Create a PythonAnywhere account +# Create a PythonAnywhere account {#pythonanywhere} {% include "/deploy/signup_pythonanywhere.md" %} diff --git a/en/intro_to_command_line/README.md b/en/intro_to_command_line/README.md index 5d7b2bbfd4c..b7c67bb6f03 100644 --- a/en/intro_to_command_line/README.md +++ b/en/intro_to_command_line/README.md @@ -18,27 +18,7 @@ The window, which is usually called the __command line__ or __command-line inter To start some experiments we need to open our command-line interface first. - - - -Go to Start menu → Windows System → Command Prompt. - -> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. - - - - - - -Go to Applications → Utilities → Terminal. - - - - - -It's probably under Applications → Accessories → Terminal, but that may depend on your system. If it's not there, just Google it. :) - - +{% include "/intro_to_command_line/open_instructions.md" %} ## Prompt @@ -47,7 +27,7 @@ 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: +If you're on Mac or Linux, you probably see a `$`, like this: {% filename %}command-line{% endfilename %} ``` @@ -58,25 +38,28 @@ $ -On Windows, it's a `>` sign, like this: +On Windows, you probably see a `>`, like this: {% filename %}command-line{% endfilename %} ``` > ``` + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + -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 a `$` or `>` and one space, but you should not 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 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. +In the tutorial, when we want you to type in a command, we will include the `$` or `>`, and occasionally more to the left. Ignore the left part and only type in the command, which starts after the prompt. ## Your first command (YAY!) -Let's start with something simple. Type this command: +Let's start by typing this command: @@ -138,7 +121,7 @@ $ pwd > cd C:\Users\olasitarska ``` -> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. @@ -146,6 +129,24 @@ You'll probably see something similar on your machine. Once you open the command --- +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + + ### List files and directories So what's in it? It'd be cool to find out. Let's see: @@ -170,13 +171,13 @@ 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 +05/08/2020 07:28 PM Applications +05/08/2020 07:28 PM Desktop +05/08/2020 07:28 PM Downloads +05/08/2020 07:28 PM Music ... ``` -> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. --- @@ -185,7 +186,7 @@ Music Now, let's go to our Desktop directory: - + {% filename %}command-line{% endfilename %} ``` @@ -193,6 +194,22 @@ $ cd Desktop ``` + + +{% filename %}command-line{% endfilename %} +``` +$ cd Desktop +``` + +Note that +the directory name "Desktop" might be translated +to the language of your Linux account. +If that's the case, you'll need to replace `Desktop` +with the translated name; +for example, `Schreibtisch` for German. + + + @@ -249,7 +266,7 @@ $ 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. :) +This little command will create a folder with the name `practice` on your desktop. You can check if it's there 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. @@ -280,7 +297,7 @@ test > cd practice > mkdir test > dir -05/08/2014 07:28 PM test +05/08/2020 07:28 PM test ``` @@ -413,6 +430,7 @@ move | mv | move file | **mo 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** +[CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) 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/intro_to_command_line/open_instructions.md b/en/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..4b5c86ee008 --- /dev/null +++ b/en/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + diff --git a/en/python_installation/README.md b/en/python_installation/README.md index 2b674d8d2c9..c2d343ec52b 100644 --- a/en/python_installation/README.md +++ b/en/python_installation/README.md @@ -4,13 +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 simpler than other programming languages, but don't worry – Python is also really powerful! # Python installation > **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. -> **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! +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! {% include "/python_installation/instructions.md" %} diff --git a/en/python_installation/instructions.md b/en/python_installation/instructions.md index 91e1666ade0..4365eea826d 100644 --- a/en/python_installation/instructions.md +++ b/en/python_installation/instructions.md @@ -2,28 +2,29 @@ > 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.6, so if you have any earlier version, you will need to upgrade it. +Django is written in Python. We need Python to do anything in Django. Let's start by installing it! We want you to install the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. +Please install normal Python as follows, even when you have Anaconda installed on your computer. -First check whether your computer is running a 32-bit version or a 64-bit version of Windows, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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. +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. -One thing to watch out for: During the installation you will notice a window marked "Setup". Make sure you tick the "Add Python 3.6 to PATH" checkbox and click on "Install Now", as shown here: +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. -![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 → Windows System → 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.) +One thing to watch out for: During the installation, you will notice a window marked "Setup". Make sure you tick the "Add Python {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): -![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) -Note: if you are using an older version of Windows (7, Vista, or any older version) and the Python 3.6.x installer fails with an error, you can try either: -1. install all Windows Updates and try to install Python 3.6 again; or -2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! -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": +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). -![Add Python to the Path, older versions](../python_installation/images/add_python_to_windows_path.png) +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. @@ -32,10 +33,10 @@ data-collapse=true ces--> > **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-361/ and download the Python installer: +You need to go to the website https://www.python.org/downloads/mac-osx/ and download the latest Python installer: * Download the *Mac OS X 64-bit/32-bit installer* file, -* Double click *python-3.6.1-macosx10.6.pkg* to run the installer. +* Double click *python-{{ book.py_release }}-macosx10.9.pkg* to run the installer. @@ -47,11 +48,17 @@ It is very likely that you already have Python installed out of the box. To chec {% filename %}command-line{% endfilename %} ``` $ python3 --version -Python 3.6.1 +Python {{ book.py_release }} ``` -If you have a different 'micro version' of Python installed, e.g. 3.6.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: +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} +``` +$ grep '^NAME=' /etc/os-release +``` +Afterwards, depending on the result, follow one of the following installation guides below this section. @@ -61,7 +68,7 @@ Type this command into your console: {% filename %}command-line{% endfilename %} ``` -$ sudo apt-get install python3.6 +$ sudo apt install python3 ``` @@ -76,7 +83,7 @@ Use this command in your console: $ sudo dnf install python3 ``` -If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. @@ -97,10 +104,11 @@ Verify the installation was successful by opening a command prompt and running t {% filename %}command-line{% endfilename %} ``` $ python3 --version -Python 3.6.1 +Python {{ book.py_release }} ``` +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. -**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. ---- diff --git a/en/python_introduction/README.md b/en/python_introduction/README.md index efeed11dc59..b10aec32908 100644 --- a/en/python_introduction/README.md +++ b/en/python_introduction/README.md @@ -1,3 +1,5 @@ +{% set warning_icon = '' %} + # Introduction to Python > Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). @@ -17,7 +19,7 @@ We want to open up a Python console, so type in `python` on Windows or `python3` {% filename %}command-line{% endfilename %} ``` $ python3 -Python 3.6.1 (...) +Python {{ book.py_release }} (...) Type "help", "copyright", "credits" or "license" for more information. >>> ``` @@ -26,9 +28,9 @@ Type "help", "copyright", "credits" or "license" for more information. 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. +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. -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`. +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. {% filename %}command-line{% endfilename %} ```python @@ -99,7 +101,7 @@ or escaping the apostrophe with a backslash (`\`): "Runnin' down the hill" ``` -Nice, huh? To see your name in uppercase letters, simply type: +Nice, huh? To see your name in uppercase letters, type: {% filename %}command-line{% endfilename %} ```python @@ -134,7 +136,7 @@ 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`: -{% filename %}command-line{% endfilename %} +{% filename %}{{ warning_icon }} command-line{% endfilename %} ```python >>> len(304023) Traceback (most recent call last): @@ -142,7 +144,9 @@ Traceback (most recent call last): 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? +We got our first error! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + + 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? {% filename %}command-line{% endfilename %} ```python @@ -168,9 +172,9 @@ Let's say we want to create a new variable called `name`: >>> name = "Ola" ``` -You see? It's easy! It's simply: name equals Ola. +We type 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`: +As you've noticed, your program didn't return anything like it did before. So how do we know that the variable actually exists? Enter `name` and hit `enter`: {% filename %}command-line{% endfilename %} ```python @@ -195,7 +199,7 @@ You can use it in functions too: 5 ``` -Awesome, right? Of course, variables can be anything – numbers too! Try this: +Awesome, right? Now, variables can be anything – numbers too! Try this: {% filename %}command-line{% endfilename %} ```python @@ -207,7 +211,7 @@ Awesome, right? Of course, variables can be anything – numbers too! Try this: But what if we used the wrong name? Can you guess what would happen? Let's try! -{% filename %}command-line{% endfilename %} +{% filename %}{{ warning_icon }} command-line{% endfilename %} ```python >>> city = "Tokyo" >>> ctiy @@ -292,7 +296,7 @@ Maybe we want to reverse that order? Let's do that! [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: +If you want to add something to your list, you can do this by typing this command: {% filename %}command-line{% endfilename %} ```python @@ -372,7 +376,7 @@ See, it's similar to a list. But you don't need to remember the index – just t What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! -{% filename %}command-line{% endfilename %} +{% filename %}{{ warning_icon }} command-line{% endfilename %} ```python >>> participant['age'] Traceback (most recent call last): @@ -382,7 +386,7 @@ 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 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. +When should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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. @@ -394,7 +398,7 @@ Dictionaries, like lists, are *mutable*, meaning that they can be changed after >>> participant['favorite_language'] = 'Python' ``` -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: +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: {% filename %}command-line{% endfilename %} ```python @@ -404,7 +408,7 @@ Like lists, using the `len()` method on the dictionaries returns the number of k 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 `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: +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'`, type in the following command: {% filename %}command-line{% endfilename %} ```python @@ -442,7 +446,7 @@ Excited for the next part? :) > For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. -A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: {% filename %}command-line{% endfilename %} ```python @@ -456,9 +460,11 @@ True True >>> 5 != 2 True +>>> len([1, 2, 3]) > len([4, 5]) +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? +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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. @@ -472,7 +478,7 @@ True False ``` -`>` and `<` are easy, but what do `>=` and `<=` mean? Read them like this: +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: - x `>` y means: x is greater than y - x `<` y means: x is less than y @@ -498,12 +504,12 @@ You can give Python as many numbers to compare as you want, and it will give you Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: -{% filename %}command-line{% endfilename %} +{% filename %}{{ warning_icon }} command-line{% endfilename %} ```python >>> 1 > 'django' Traceback (most recent call last): File "", line 1, in -TypeError: unorderable types: int() > str() +TypeError: '>' not supported between instances of 'int' and 'str' ``` Here you see that just like in the expression, Python is not able to compare a number (`int`) and a string (`str`). @@ -511,13 +517,13 @@ Instead, it shows a **TypeError** and tells us the two types can't be compared t ## Boolean -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. +Incidentally, you just learned about a new type of object in Python. It's called __Boolean__. There are only two Boolean objects: - True - False -But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). __true, TRUE, and 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 uppercase, with the rest of the letters lowercased). __true, TRUE, and tRUE won't work – only True is correct.__ (The same applies to 'False' as well.) Booleans can be variables, too! See here: @@ -558,7 +564,7 @@ So far we've been writing all our python code in the interpreter, which limits u - 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, type the `exit()` function {% filename %}command-line{% endfilename %} ```python @@ -568,7 +574,7 @@ $ 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: +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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): {% filename %}editor{% endfilename %} ```python @@ -598,13 +604,15 @@ $ cd ~/Desktop -On Linux, it will be like this (the word "Desktop" might be translated to your local language): +On Linux, it will be like this: {% filename %}command-line{% endfilename %} ``` $ cd ~/Desktop ``` +(Remember that the word "Desktop" might be translated to your local language.) + @@ -629,7 +637,7 @@ And on Windows Powershell, it will be like this: -If you get stuck, just ask for help. +If you get stuck, ask for help. That's exactly what the coaches are here for! Now use Python to execute the code in the file like this: @@ -663,7 +671,7 @@ if 3 > 2: If we were to save and run this, we'd see an error like this: -{% filename %}command-line{% endfilename %} +{% filename %}{{ warning_icon }} command-line{% endfilename %} ``` $ python3 python_intro.py File "python_intro.py", line 2 @@ -679,7 +687,7 @@ if 3 > 2: print('It works!') ``` -Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. Save it and give it another run: @@ -711,7 +719,7 @@ $ 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: +If 2 were a greater number than 5, then the second command would be executed. Let's see how `elif` works: {% filename %}python_intro.py{% endfilename %} ```python @@ -796,7 +804,7 @@ Time for the last part of this chapter! 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: +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 give it a go. Replace the code in **python_intro.py** with the following: {% filename %}python_intro.py{% endfilename %} ```python @@ -809,7 +817,7 @@ hi() Okay, our first function is ready! -You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. Let's run this now and see what happens: @@ -825,7 +833,7 @@ Note: if it didn't work, don't panic! The output will help you to figure why: - If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. - If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. -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: +Let's build our first function with parameters. We will change the previous example – a function that says 'hi' to the person running it – with a name: {% filename %}python_intro.py{% endfilename %} ```python @@ -849,7 +857,7 @@ 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: -{% filename %}command-line{% endfilename %} +{% filename %}{{ warning_icon }} command-line{% endfilename %} ``` $ python3 python_intro.py Traceback (most recent call last): @@ -899,7 +907,7 @@ 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! -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? Replace the content of your file with the following: {% filename %}python_intro.py{% endfilename %} ```python @@ -941,7 +949,7 @@ We want to greet all of them by their name. We have the `hi` function to do that for name in girls: ``` -The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. Here is the full code that will be in the file: @@ -1002,6 +1010,9 @@ Note that the second of these two numbers is not included in the list that is ou 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! +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + 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 56efeafa4a2..bbf0644d799 100644 --- a/en/template_extending/README.md +++ b/en/template_extending/README.md @@ -18,39 +18,41 @@ blog post_list.html ``` -Then open it up and copy everything from `post_list.html` to `base.html` file, like this: +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: {% filename %}blog/templates/blog/base.html{% endfilename %} ```html -{% load staticfiles %} +{% load static %} + Django Girls blog - - + - + -
+
-
+
{% for post in posts %} -
-
+
+
-

{{ post.title }}

+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %}
-
+
``` @@ -60,17 +62,19 @@ Then in `base.html`, replace your whole `` (everything between `` an {% filename %}blog/templates/blog/base.html{% endfilename %} ```html - -
+ +
-
+
{% block content %} {% endblock %}
-
+
``` @@ -83,19 +87,19 @@ Then in `base.html`, replace your whole `` (everything between `` an ``` But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. -Now save `base.html` and open your `blog/templates/blog/post_list.html` again. +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} {% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% for post in posts %} -
-
+
+
-

{{ post.title }}

+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %} ``` @@ -108,13 +112,13 @@ Time to add block tags to this file! ```html {% block content %} {% for post in posts %} -
-
+
+
-

{{ post.title }}

+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %} {% endblock %} ``` @@ -127,17 +131,17 @@ Only one thing left. We need to connect these two templates together. This is w {% block content %} {% for post in posts %} -
-
+
+
-

{{ post.title }}

+ +

{{ post.title }}

{{ post.text|linebreaksbr }}

-
+ {% endfor %} {% endblock %} ``` -That's it! Check if your website is still working properly. :) +That's it! Save the file, and check if your website is still working properly. :) > 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 52f050703a5..cb3f8012800 100644 --- a/en/whats_next/README.md +++ b/en/whats_next/README.md @@ -4,21 +4,37 @@ Congratulate yourself! __You're totally awesome__. We're proud! <3 ### What to do now? -Take a break and relax. You have just done something really huge. +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](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](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). +Yes! There are a _lot_ of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. -Later on, you can try the resources listed below. They're all very recommended! -- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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/) +#### Django +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) - [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) -- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) -- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + + +#### HTML, CSS and JavaScript +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! diff --git a/eo-UY/GLOSSARY.md b/eo-UY/GLOSSARY.md new file mode 100644 index 00000000000..3f33fe11092 --- /dev/null +++ b/eo-UY/GLOSSARY.md @@ -0,0 +1,3 @@ +# kodredaktilo + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/eo-UY/README.md b/eo-UY/README.md new file mode 100644 index 00000000000..7edeaa56cdc --- /dev/null +++ b/eo-UY/README.md @@ -0,0 +1,51 @@ +# Django-Knabinoj-Lernilo + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> Ĉi-tiu verko estas licencita laŭ la tutmonda licenco Krea Komunaĵ-Atribuad-Divido Samkondiĉa 4.0. Por vidi kopion de ĉi-tiu licenco vizitu https://creativecommons.org/licenses/by-sa/4.0/ + +## Bonvenon + +Bonvenon al la Django-Knabino-Lernilo! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Introduction + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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. + +Ni esperas, ke ni povos igi, ke vi amu teĥnikaron tiom ege kiom ni! + +## Kion vi lernos dum la lernilo? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +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 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! + +Bone, [ni komencu ĉe la komenco…](./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. + +## About and contributing + +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). + +## Ĉu vi ŝatus helpi nin traduki la memlernilon al aliajn lingvojn? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/eo-UY/SUMMARY.md b/eo-UY/SUMMARY.md new file mode 100644 index 00000000000..aa4fba0c740 --- /dev/null +++ b/eo-UY/SUMMARY.md @@ -0,0 +1,35 @@ +# Enhavo + +* [Enkonduko](README.md) +* [Installation](installation/README.md) + * [Command Line](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Kodredaktilo](installation/README.md#code-editor) + * [Virtual Environment](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Installation (chromebook)](chromebook_setup/README.md) +* [Kiel la interreto funkcias](how_the_internet_works/README.md) +* [Introduction to command line](intro_to_command_line/README.md) +* [Python installation](python_installation/README.md) +* [Kodredaktilo](code_editor/README.md) +* [Introduction to Python](python_introduction/README.md) +* [Kio estas Django?](django/README.md) +* [Django installation](django_installation/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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/eo-UY/chromebook_setup/README.md b/eo-UY/chromebook_setup/README.md new file mode 100644 index 00000000000..03249a84d41 --- /dev/null +++ b/eo-UY/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook setup + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/eo-UY/chromebook_setup/instructions.md b/eo-UY/chromebook_setup/instructions.md new file mode 100644 index 00000000000..9ddf3dca4ca --- /dev/null +++ b/eo-UY/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Vi povas [salti ĉi-tiun ĉapitron](http://tutorial.djangogirls.org/en/installation/#install-python), se vi ne uzas kromiolibron. Se vi uzas, via instalado estos iomete malsama. Vi povas ignori la reston de la instalinstrukcioj. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Cloud IDE estas ilo, kiu disponigas al vi kodoredaktilon kaj aliron al komputilo funkciante en la reto, kie vi povas instali, skribi kaj funkciigi la programaron. Dum la daŭro de la lernsesio, Cloud IDE agas kiel via *loka maŝino*. Vi ankoraŭ estos lanĉante komandojn en terminala interfaco same kiel viaj samklasanoj en OS X, Ubuntu, aŭ Vindozo, sed via terminalo estos konektita al komputilo funkciante aliloke, tiu cloud IDE estos agordita por vi. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). You can choose one of the cloud IDEs, and follow the instruction of the cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Go to [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Sign up for an account +3. Click *New Server* and choose the Django app +4. Click Terminal button(on the left side of the window) + +Now you should see an interface with a sidebar, buttons at the left. Click "Terminal" button to open terminal window with prompt like this: + +{% filename %}Terminal{% endfilename %} + + $ + + +The terminal on the PaizaCloud Cloud IDE is prepared for your instructions. You can resize or maximize that window to make it a bit bigger. + +#### AWS Cloud9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + yourusername:~/workspace $ + + +This bottom area is your terminal. You can use the terminal to send instructions to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### 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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/eo-UY/code_editor/README.md b/eo-UY/code_editor/README.md new file mode 100644 index 00000000000..2e98f817cac --- /dev/null +++ b/eo-UY/code_editor/README.md @@ -0,0 +1,11 @@ +# Kodredaktilo + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +Vi baldaŭ skribas vian unuan lineon de kodo, tial estas tempo elŝuti kodredaktilon! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. The cloud IDE you chose (PaizaCloud Cloud IDE or AWS Cloud9) includes a code editor, and when you open a file in your IDE from the File menu, you will automatically be using the editor. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/eo-UY/code_editor/instructions.md b/eo-UY/code_editor/instructions.md new file mode 100644 index 00000000000..678ecb96ae5 --- /dev/null +++ b/eo-UY/code_editor/instructions.md @@ -0,0 +1,37 @@ +Estas multaj diversaj redaktiloj kaj la elekto esence okazas surbaze de persona prefero. Most Python programmers use complex but extremely powerful IDEs (Integrated Development Environments), such as PyCharm. Por komencanto tamen tio verŝajne malpli taŭgas; nia rekomendoj estas same potenca, sed multe pli simpla. + +Nia sugestoj troviĝas sube, sed bonvolu demandi al via trejnisto, kio estas ilia prefero – plifalicos ricevi helpon de ili. + +## Visual Studio Code + +Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + +[Elŝutu ĝin ĉi tie](https://code.visualstudio.com/) + +## Gedit + +Gedit estas malfermitfonta, senpaga redaktilo, havebla por ĉiuj operaciumoj. + +[Elŝutu ĝin ĉi tie](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[Elŝutu ĝin ĉi tie](https://www.sublimetext.com/3) + +## Atom + +Atom estas alia populara redaktilo. Ĝi estas senpaga, malfermitfonta kaj havebla por Vindozo, OS X kaj Linukso. Atom estas programata de [GitHub](https://github.com/). + +[Elŝutu ĝin ĉi tie](https://atom.io/) + +## Kial instalu kodredaktilon? + +Vi eble scivolas, kial ni instalas tion speciala kodredaktila programaro anstataŭ uzi iel kiel Vordo (angle: Microsoft Word) aŭ Notepado (angle: Notepad). + +La unua kialo estas, ke kodo devas esti **pura teksto**, kaj la problemo de programoj kiel Vordo kaj TekstEdito (angle: TextEdit) estas, ke ili ne vere faras puran tekston. Ili faras riĉan tekston (kun tiparo kaj formatado), uzante tajloritajn formatojn kiel [RTF (Riĉtekstformato, angle: Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +La dua kialo estas, ke kodredaktiloj estas speciale farita por redakti kodon, do ili havas helpemajn funkciojn kiel markadigi kodon kun koloroj laŭ ĝia signifo aŭ aŭtomate fermi citilojn por vi. + +Ni spertos tion poste. Baldaŭ vi iĝos pensanta pri via fidinda malnova redaktilo kiel unu el viaj plej ŝatataj iloj. :) \ No newline at end of file diff --git a/eo-UY/css/README.md b/eo-UY/css/README.md new file mode 100644 index 00000000000..cf783590b6e --- /dev/null +++ b/eo-UY/css/README.md @@ -0,0 +1,330 @@ +# 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 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? 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: https://getbootstrap.com/ + +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, open up your `.html` file in the code editor and add this to the `` section: + +{% 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. So go ahead, open your website and refresh the page. Here it is! + +![Figure 14.1](images/bootstrap1.png) + +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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +Django already knows where to find the static files for the built-in "admin" app. Now we 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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +But let's do at least a little. Maybe we could change the color of our headers? 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, h2 a { + color: #C25100; +} + +``` + +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element; the `h2 a` selector does the same thing for `h2` elements. 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 `#C25100`, which is a dark orange. Or you can put your own color here, but make sure it has good contrast against a white background! + +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 element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file in the code editor and add this line at the very beginning of it: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +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 +<link rel="stylesheet" href="{% static 'css/blog.css' %}"> +``` + +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 be overriden by 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 static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Figure 14.2](images/color2.png) + +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 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 +<link href="//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css"> +``` + +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). + +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, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Bonega! + +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. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Figure 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/eo-UY/deploy/README.md b/eo-UY/deploy/README.md new file mode 100644 index 00000000000..18ad585d6e5 --- /dev/null +++ b/eo-UY/deploy/README.md @@ -0,0 +1,246 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Krei nian Git-deponejon + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/eo-UY/deploy/install_git.md b/eo-UY/deploy/install_git.md new file mode 100644 index 00000000000..53fbe28d617 --- /dev/null +++ b/eo-UY/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in word processor programs (e.g., Microsoft Word or LibreOffice Writer), but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for two: in the step where it asks to choose your editor, you should pick Nano, and in the step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/eo-UY/deploy/signup_pythonanywhere.md b/eo-UY/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..555e36731dd --- /dev/null +++ b/eo-UY/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use it for hosting our site, live and on the Internet. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/eo-UY/django/README.md b/eo-UY/django/README.md new file mode 100644 index 00000000000..0f2c4ef30f6 --- /dev/null +++ b/eo-UY/django/README.md @@ -0,0 +1,27 @@ +# What is Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. + +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc. + +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. + +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/eo-UY/django_admin/README.md b/eo-UY/django_admin/README.md new file mode 100644 index 00000000000..156eae05654 --- /dev/null +++ b/eo-UY/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/eo-UY/django_forms/README.md b/eo-UY/django_forms/README.md new file mode 100644 index 00000000000..68676f99fa5 --- /dev/null +++ b/eo-UY/django_forms/README.md @@ -0,0 +1,479 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Security + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/eo-UY/django_installation/README.md b/eo-UY/django_installation/README.md new file mode 100644 index 00000000000..9b024008342 --- /dev/null +++ b/eo-UY/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/eo-UY/django_installation/instructions.md b/eo-UY/django_installation/instructions.md new file mode 100644 index 00000000000..fc965146844 --- /dev/null +++ b/eo-UY/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/eo-UY/django_models/README.md b/eo-UY/django_models/README.md new file mode 100644 index 00000000000..f2a68a8727f --- /dev/null +++ b/eo-UY/django_models/README.md @@ -0,0 +1,201 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/eo-UY/django_orm/README.md b/eo-UY/django_orm/README.md new file mode 100644 index 00000000000..ffe309bd81e --- /dev/null +++ b/eo-UY/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### All objects + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/eo-UY/django_start_project/README.md b/eo-UY/django_start_project/README.md new file mode 100644 index 00000000000..3767c62e17f --- /dev/null +++ b/eo-UY/django_start_project/README.md @@ -0,0 +1,260 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/eo-UY/django_templates/README.md b/eo-UY/django_templates/README.md new file mode 100644 index 00000000000..db2d20c4d4e --- /dev/null +++ b/eo-UY/django_templates/README.md @@ -0,0 +1,108 @@ +# Django templates + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Figure 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Figure 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Figure 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/eo-UY/django_urls/README.md b/eo-UY/django_urls/README.md new file mode 100644 index 00000000000..d37a5e3c2fd --- /dev/null +++ b/eo-UY/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/eo-UY/django_views/README.md b/eo-UY/django_views/README.md new file mode 100644 index 00000000000..ab271e0914f --- /dev/null +++ b/eo-UY/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/eo-UY/dynamic_data_in_templates/README.md b/eo-UY/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..5a6ef017adf --- /dev/null +++ b/eo-UY/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/eo-UY/extend_your_application/README.md b/eo-UY/extend_your_application/README.md new file mode 100644 index 00000000000..c70a2db97ff --- /dev/null +++ b/eo-UY/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/eo-UY/how_the_internet_works/README.md b/eo-UY/how_the_internet_works/README.md new file mode 100644 index 00000000000..bf9484bc4bb --- /dev/null +++ b/eo-UY/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# Kiel la interreto funkcias + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +OK, but you want to know how the Internet looks, right? + +Ni desegnis bildon por vi. Ĝi aspektas tiel: + +![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: + +![Figure 1.2](images/internet_3.png) + +Ĝi fascinas, ĉu? But 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. + +Ĝi aspektas tiel: + +![Figure 1.3](images/internet_2.png) + +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. + +![Figure 1.4](images/internet_4.png) + +That's how it works - you send messages and you expect some response. 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 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, 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 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! \ No newline at end of file diff --git a/eo-UY/html/README.md b/eo-UY/html/README.md new file mode 100644 index 00000000000..27c81ea68be --- /dev/null +++ b/eo-UY/html/README.md @@ -0,0 +1,227 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is 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 `TemplateDoesNotExist`, try to restart your server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Figure 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +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 line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Figure 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to GitHub + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% 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. + +{% 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: + +{% 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 %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/eo-UY/installation/README.md b/eo-UY/installation/README.md new file mode 100644 index 00000000000..0467fcad4ac --- /dev/null +++ b/eo-UY/installation/README.md @@ -0,0 +1,68 @@ +# 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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). Se vi volas, vi povas elekti instali tuj ĉion, kio estas en ĉi tio paĝo. Sed se vi volas komenci lerni aferojn antaŭ ol instali aron da aĵoj en vian komputilon, preterlasu ĉi tion ĉapitron kaj ni ekspliku al vi la instalerojn poste, kiam ili bezonatos. + +Bonŝancon! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Installation + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#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: + +* [Kiel la interreto funkcias](../how_the_internet_works/README.md) + +* [Introduction to the command line](../intro_to_command_line/README.md) + +* [Introduction to Python](../python_introduction/README.md) + +* [Kio estas 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. \ No newline at end of file diff --git a/eo-UY/intro_to_command_line/README.md b/eo-UY/intro_to_command_line/README.md new file mode 100644 index 00000000000..e1f8097b348 --- /dev/null +++ b/eo-UY/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Your first command (YAY!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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 (aŭ del) | rm | delete a file | **del c:\test\test.txt** | +| rmdir /S | rm -r | delete a directory | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/eo-UY/intro_to_command_line/open_instructions.md b/eo-UY/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/eo-UY/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/eo-UY/python_installation/README.md b/eo-UY/python_installation/README.md new file mode 100644 index 00000000000..8470b71f1f4 --- /dev/null +++ b/eo-UY/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/eo-UY/python_installation/instructions.md b/eo-UY/python_installation/instructions.md new file mode 100644 index 00000000000..7897de54338 --- /dev/null +++ b/eo-UY/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 estas skribita en Python. Ni bezonas Python por fari iu ajn en Django. Let's start by installing it! We want you to install the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/eo-UY/python_introduction/README.md b/eo-UY/python_introduction/README.md new file mode 100644 index 00000000000..fca9040b58f --- /dev/null +++ b/eo-UY/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introduction to Python + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Ni skribu kelkan kodon! + +## Python prompt + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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. + +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Saluton " + "Ola" +'Saluton Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ho, mia kor'." +"Ho, mia kor'." +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Ho, mia kor\'.' +"Ho, mia kor'." +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Summary + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y signifas: x estas pli ol y +- x `<` y signifas: x estas malpli ol y +- x `<=` y signifas: x estas malpli ol aŭ egala al y +- x `>=` y signifas: x estas pli ol aŭ egala al y + +Bonege! Ĉu vi volas fari plu? Provu ĉi-tio: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True (vera) +- False (malvera) + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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, type the `exit()` function + +{% 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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Saluton, Djangoaj virinoj!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +Now use Python to execute the code in the file like this: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Saluton, Djangoaj virinoj! + + +Note: on Windows 'python3' is not recognized as a command. Instead, use 'python' to execute the file: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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('Ĝi funkcias!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% filename %}command-line{% endfilename %} + +```python +$ python3 python_intro.py +Ĝi funkcias! +``` + +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 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 ja estas pli granda ol 2') +else: + print('5 ne estas pli granda ol 2') +``` + +When this is run it will print out: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + 5 ja estas pli granda ol 2 + + +If 2 were a greater number than 5, then the second command would be executed. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% 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! + +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/eo-UY/template_extending/README.md b/eo-UY/template_extending/README.md new file mode 100644 index 00000000000..7f3697b7fd4 --- /dev/null +++ b/eo-UY/template_extending/README.md @@ -0,0 +1,151 @@ +# Template extending + +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. + +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 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 + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/eo-UY/whats_next/README.md b/eo-UY/whats_next/README.md new file mode 100644 index 00000000000..97c41870d93 --- /dev/null +++ b/eo-UY/whats_next/README.md @@ -0,0 +1,43 @@ +# What's next? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](https://twitter.com/djangogirls) to stay up to date. + +### Can you recommend any further resources? + +Yes! There are a *lot* of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. + +#### Django + +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS and JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! \ No newline at end of file diff --git a/es-ES/GLOSSARY.md b/es-ES/GLOSSARY.md new file mode 100644 index 00000000000..9a6912eacf6 --- /dev/null +++ b/es-ES/GLOSSARY.md @@ -0,0 +1,3 @@ +# editor de código + +Un editor de código es una aplicación que te permite escribir código y guardarlo en ficheros del disco de tu ordenador. Puedes ver dónde descargar uno en el [capítulo Editor de código](./code_editor/README.md) \ No newline at end of file diff --git a/es-ES/README.md b/es-ES/README.md new file mode 100644 index 00000000000..7914b968aac --- /dev/null +++ b/es-ES/README.md @@ -0,0 +1,51 @@ +# Tutorial de Django Girls + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> 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/ + +## Bienvenido/a + +¡Bienvenido/a al tutorial de las Django Girls! Estamos felices de verte por aquí. :) En este tutorial, te llevaremos en un viaje a las entrañas de las tecnologías web, dándote una idea de todos los fragmentos y piezas que necesitan encajarse para hacer que las redes funcionen tal y como conocemos. + +Con todo lo que hay por conocer, esto va a ser sin duda una aventura, pero no te preocupes. Ya has tenido el coraje de venir aquí, así que todo irá bien. :) + +## Introducción + +¿Alguna vez has tenido la sensación de que el mundo es cada vez más tecnológico? ¿que cada vez lo entiendes menos? ¿Alguna vez te has planteado crear un sitio web pero no sabías por donde empezar? ¿Has pensado alguna vez que el mundo del software es demasiado complicado como para intentar hacer algo por tu cuenta? + +Bueno, ¡tenemos buenas noticias! Programar no es tan difícil como parece y queremos demostrarte lo divertido que puede llegar a ser. + +Este tutorial no te convertirá en programadora de la noche a la mañana. Sí quieres ser buena en esto, necesitarás meses o incluso años de aprendizaje y práctica. Sin embargo queremos enseñarte que programar o crear sitios web no es tan complicado como parece. Intentaremos explicar las cosas lo mejor que podamos, para perderle el miedo a la tecnología. + +¡Esperamos conseguir que te guste la tecnología tanto como a nosotras! + +## ¿Qué aprenderás con este tutorial? + +Cuando termines el tutorial, tendrás una aplicación web sencilla y funcional: tu propio blog. Te mostraremos como ponerla en línea, ¡para que otros puedan ver tu trabajo! + +Tendrá (más o menos) esta pinta: + +![Figure 0.1](images/application.png) + +> Si estás siguiendo este tutorial por tu cuenta y no tienes un mentor que te ayude en caso de dificultades, tenemos un chat para ti: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). ¡Hemos pedido a mentores y asistentes de ediciones anteriores, que pasen por allí de vez en cuando para echar una mano a otras con el tutorial! ¡No tengas miedo de preguntar ahí! + +Bien, [empecemos por el comienzo...](./how_the_internet_works/README.md) + +## Seguir el tutorial desde casa + +Participar en un taller de Django Girls en vivo es genial, pero somos conscientes de que no siempre es posible hacerlo. Por eso, te recomendamos hacer este tutorial en casa. Para las que estáis en casa, estamos preparando videos que facilitarán seguir el tutorial por tu cuenta. Todavía está en progreso, pero cada vez hay más cosas explicadas en el canal de YouTube [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) (Nota: en inglés). + +En cada capítulo hay un enlace que lleva al video correspondiente (si lo hay). + +## Sobre nosotras y Cómo contribuir + +Este tutorial lo mantiene [DjangoGirls](https://djangogirls.org/). Si encuentras algún error o quieres actualizar el tutorial, por favor [sigue la guía de cómo contribuir](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## ¿Te gustaría ayudarnos a traducir el tutorial a otros idiomas? + +Actualmente, las traducciones se hacen en la plataforma crowdin.com, en el siguiente enlace: + +https://crowdin.com/project/django-girls-tutorial + +Si tu idioma no aparece en la lista de [crowdin](https://crowdin.com/), por favor [abre un nuevo issue](https://github.com/DjangoGirls/tutorial/issues/new) con el idioma para que podamos añadirlo. \ No newline at end of file diff --git a/es-ES/SUMMARY.md b/es-ES/SUMMARY.md new file mode 100644 index 00000000000..9feb1f3c8b4 --- /dev/null +++ b/es-ES/SUMMARY.md @@ -0,0 +1,35 @@ +# Contenido + +* [Introducción](README.md) +* [Instalación](installation/README.md) + * [Línea de Comandos](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Editor de texto](installation/README.md#code-editor) + * [Entorno Virtual](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Instalación (chromebook)](chromebook_setup/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) +* [¡Tu primer proyecto en Django!](django_start_project/README.md) +* [Modelos en Django](django_models/README.md) +* [Administrador de Django](django_admin/README.md) +* [¡Despliega!](deploy/README.md) +* [URLs en Django](django_urls/README.md) +* [Vistas en Django - ¡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 las plantillas](dynamic_data_in_templates/README.md) +* [Plantillas de Django](django_templates/README.md) +* [CSS - ¡Que quede bonito!](css/README.md) +* [Extendiendo plantillas](template_extending/README.md) +* [Amplía tu aplicación](extend_your_application/README.md) +* [Formularios de Django](django_forms/README.md) +* [¿Y ahora qué?](whats_next/README.md) \ No newline at end of file diff --git a/es-ES/chromebook_setup/README.md b/es-ES/chromebook_setup/README.md new file mode 100644 index 00000000000..842f198d5ee --- /dev/null +++ b/es-ES/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Configuración de Chromebook + +> **Nota** Si ya has trabajado en los [pasos de instalación](../installation/README.md), no es necesario que hagas esto de nuevo - puedes ir directamente a [Introducción a Python](../python_introduction/README.md). + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/es-ES/chromebook_setup/instructions.md b/es-ES/chromebook_setup/instructions.md new file mode 100644 index 00000000000..e4ad4c9f89c --- /dev/null +++ b/es-ES/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Puedes [saltarte esta sección](http://tutorial.djangogirls.org/en/installation/#install-python) en caso de que no estés usando un Chromebook. Si lo usas, tu experiencia de instalación será algo diferente. Puedes ignorar el resto de las instrucciones de instalación. + +### IDE en la nube (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Cloud IDE es una herramienta que te da un editor de código y acceso a un ordenador conectado a internet en el que puedes instalar, escribir y ejecutar software. Durante este tutorial, el IDE en la nube te servirá como tu *máquina local*. Seguirás corriendo comandos en una interfaz de terminal justo como tus compañeros de clase en OS X, Ubuntu, o Windows, pero tu terminal será conenctada a una computadora corriendo en algún otro lugar que cloud IDE establecerá por tí. Aquí tienes las instrucciones para varios IDEs de la nube (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). Puedes elegir uno de los IDEs en la nube, y seguir sus instrucciones. + +#### PaizaCloud Cloud IDE + +1. Ve a [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Crea una cuenta +3. Haga clic en *New Server* y elija la aplicación Django +4. Haga clic en el botón Terminal (al lado izquierdo de la ventana) + +Ahora deberías ver una interfaz con una barra y botones en la izquierda. Haz click en al botón "Terminal" para abrir la ventana de la terminal con un símbolo de sistema como este: + +{% filename %}Terminal{% endfilename %} + + $ + + +La terminal en el Cloud IDE de PaizaCloud está preparada para ejecutar tus instrucciones. Puedes redimensionar o maximizar la ventana para hacerla un poco más grande. + +#### AWS Cloud9 + +Actualmente Cloud 9 requiere que te registres con AWS e ingreses la información de una tarjeta de crédito. + +1. Instala Cloud 9 desde la [Chrome web store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Ve a [c9.io](https://c9.io) y haz clic en *Get started with AWS Cloud9* +3. Regístrate en una cuenta AWS (requiere información de tarjeta de crédito, pero puedes usar gratis) +4. En el panel de control AWS, introduzca *Cloud9* en la barra de búsqueda y haga clic en ella +5. En el panel de control de Cloud 9, haga clic en *Create environment* +6. Nómbralo *django-girls* +7. Mientras configura los ajustes, seleccione *Create a new instance for environment (EC2)* para "Environment Type" y seleccione el valor *t2.micro* para "Instance type" (debería decir "Free-tier eligible."). La configuración por defecto de ahorro de costes está bien y puede mantener los otros valores por defecto. +8. Haz clic en *Next step* +9. Haz clic en *Create environment* + +Ahora deberías ver una interfaz con una barra, una gran ventana principal con algún texto y una ventana pequeña en la parte inferior que se vería así: + +{% filename %}bash{% endfilename %} + + yourusername:~/workspace $ + + +El área de abajo es tu terminal. Puedes usar el terminal para enviar instrucciones al ordenador remoto Cloud 9. Puedes redimensionar la ventana para hacerla un poco mas grande + +#### IDE en la nube de Glitch.com + +1. Entra en [Glitch.com](https://glitch.com/) +2. Regístrate y crea una cuenta (https://glitch.com/signup) o usa tu cuenta de GitHub si tienes una (lee las instrucciones para GitHub a continuación) +3. Haz clic en *Proyecto nuevo* y selecciona *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### Entorno Virtual + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/es-ES/code_editor/README.md b/es-ES/code_editor/README.md new file mode 100644 index 00000000000..c801a8819f6 --- /dev/null +++ b/es-ES/code_editor/README.md @@ -0,0 +1,11 @@ +# Editor de código + +> Para los lectores en casa: este capitulo se explica en el video [Instalando Python & Editor de Código](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s). + +Estás a punto de escribir tu primera línea de código, así que ¡es hora de descargar un editor de código! + +> **Nota** Si estas usando un Chromebook, omite este capitulo y asegurate de seguir las instrucciones de [Instalacion de Chromebook](../chromebook_setup/README.md). El cloud IDE que elegiste (Paizacloud Cloud IDE o AWS cloud9) incluye un editor de código, y cuando tu abres un archivo en tu IDE desde el menú de archivos, tu estarás automáticamente usando el editor. +> +> **Nota** Quizás ya hayas hecho esto en el [Capítulo de instalación](../installation/README.md) - si es así, ¡Puedes ir directamente al siguiente capítulo! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/es-ES/code_editor/instructions.md b/es-ES/code_editor/instructions.md new file mode 100644 index 00000000000..398cbd64c64 --- /dev/null +++ b/es-ES/code_editor/instructions.md @@ -0,0 +1,37 @@ +Hay muchos diferentes editores y se reduce en gran parte a la preferencia personal La mayoría de programadores de Python usan complejos pero muy potentes IDEs (Entornos de Desarrollo Integrados), como PyCharm. Como principiante, de cualquier manera, es probable que sea menos adecuado; nuestras recomendaciones son igual de poderosas, pero más simples. + +Nuestras sugerencias están abajo, pero siéntete libre de preguntarle a tu tutor cuales son sus preferencias - será mucho mas simple obtener ayuda de ellos. + +## Visual Studio Code + +Visual Studio Code es un editor de código fuente desarrollado por Microsoft para Windows, Linux y macOS. Incluye soporte para depuración, control Git embebido, resaltado de sintaxis, finalización inteligente de código, fragmentos y refactorización de código. + +[Descárgalo aquí](https://code.visualstudio.com/) + +## Gedit + +Gedit es un editor gratuito de código abierto, disponible para todos los sistemas operativos. + +[Descárgalo aquí](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text es un editor muy popular con un periodo de prueba gratis, y está disponible para todos los sistemas operativos. + +[Descárgalo aquí](https://www.sublimetext.com/3) + +## Atom + +Atom es otro editor popular. Es gratis, de código abierto y está disponible para Windows, OS X and Linux. Atom esta desarrollado por [Github](https://github.com/). + +[Descárgalo aquí](https://atom.io/) + +## ¿Por qué estamos instalando un editor de código? + +Tú podrías estar preguntándote por qué estamos instalando éste especial software editor de código, en vez de usar algo como Word o Notepad. + +La primera razón es que el código necesita ser **texto plano**, y el problema con programas como Word y Textedit es que ellos actualmente no produce texto plano, ellos producen texto rico (con fuentes y formatos), usando formatos personalizados como [RTF ( Formato del Texto Enriquecido, del inglés Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +La segunda razón es que los editores de código son especializados para editar código, así ellos pueden proveer características útiles como destacar código con color acorde a su significado, o automáticamente cerrando citas para ti. + +Veremos todo esto en acción más adelante. Pronto, llegarás a pensar que tu viejo confiable editor de código es una de tus herramientas favoritas :) \ No newline at end of file diff --git a/es-ES/css/README.md b/es-ES/css/README.md new file mode 100644 index 00000000000..ceeec475c62 --- /dev/null +++ b/es-ES/css/README.md @@ -0,0 +1,330 @@ +# CSS - ¡Que quede bonito! + +Nuestro blog todavía es un poco feo, ¿no te parece? ¡Es hora de ponerlo bonito! Para eso, vamos a usar CSS. + +## ¿Qué es CSS? + +El lenguaje CSS (las siglas en inglés de hojas de estilos en cascada, o Cascading Style Sheets), sirve para describir la apariencia y el formato de un sitio web escrito en un lenguaje de marcado (como HTML). Has de cuenta que es como aplicar maquillaje a nuestra página web. ;) + +Pero no queremos empezar de cero otra vez, ¿verdad? Una vez más vamos a utilizar algo que otros programadores ya han publicaron gratis en internet. Reinventar la rueda todo el tiempo no es nada divertido. + +## ¡Comenzemos a usar Bootstrap! + +Bootstrap es uno de los frameworks de HTML y CSS mas populares para desarrollar para sitios web atractivos: https://getbootstrap.com/ + +Fue escrito por programadores que trabajaban en Twitter. ¡Ahora lo mantienen y desarrollan voluntarios de todo el mundo! + +## Instala Bootstrap + +Para instalar Bootstrap, abre tu fichero `.html` en el editor de código y añade esto a la sección ``: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Esto no añade ningún archivo a tu proyecto. Solo apunta a archivos que ya existen en Internet. Así que adelante, accede a tu sitio web y actualiza la página ¡Aquí la tienes! + +![Figura 14.1](images/bootstrap1.png) + +¡Ya luce mucho mejor! + +## Archivos estáticos en Django + +Finalmente vamos a mirar más de cerca esto que hemos estado llamando **archivos estáticos**. Los archivos estáticos son todas tus imágenes y archivos CSS. Su contenido no depende del contexto requerido y siempre será el mismo para cada usuario. + +### Dónde poner los archivos estáticos para Django + +Django ya sabe dónde encontrar los archivos estáticos para la incorporación de la aplicación "admin". Ahora necesitamos añadir los archivos estáticos de nuestra aplicación, `blog`. + +Hacemos eso creando una carpeta llamada `static` dentro de la aplicación blog: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │ └── templates + └── mysite + + +Django automáticamente encontrará cualquier carpeta llamada "static" dentro de cualquiera de las carpetas de tus aplicaciones. Entonces va a ser posible usar su contenido como archivos estáticos. + +## ¡Tu primer archivo CSS! + +Vamos a crear un archivo CSS, para añadir tu propio estilo a la página. Crea un nuevo directorio llamado `css` dentro de la carpeta `static`. A continuación, crea un nuevo archivo llamado `blog.css` dentro de la carpeta `css`. ¿Listos? + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +¡Vamos a escribir algo de CSS! Abre el archivo `blog/static/css/blog.css` en el editor de código. + +No vamos a profundizar demasiado en cómo personalizar y aprender CSS. Pero te podemos recomendar un un curso gratuito de CSS al final de esta página por si quieres aprender más. + +Pero vamos a hacer al menos un poco. ¿Quizas podamos cambiar el color de nuestros encabezados? Los ordenadores utilizan códigos especiales para expresar los colores. Estos códigos empiezan con `#` seguidos por 6 letras (A-F) y números (0-9). Por ejemplo, el código del color azul es `#0000FF`. Puedes encontrar los códigos de muchos colores aquí: http://www.colorpicker.com/ y en otras páginas web. También puedes utilizar [colores predefinidos](http://www.w3schools.com/colors/colors_names.asp) utilizando su nombre en inglés, como `red` y `green`. + +En el archivo `blog/static/css/blog.css` deberías añadir el siguiente código: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1 a` es un selector CSS. Esto significa que estamos aplicando nuestros estilos a cualquier elemento de `a` dentro de un elemento de `h1`; el selector `h2 a` hace lo mismo para los elementos de `h2`. Así, cuando tenemos algo como `

link

`, se aplicará el estilo `h1 a`. En este caso, le estamos diciendo que cambie el color a un `#C25100`, que es un naranjo oscuro. O puedes poner tu propio color aqui, ¡pero asegurate que tenga un buen contraste contra un fondo blanco! + +En un archivo CSS se definen los estilos de los elementos que aparecen en el archivo HTML. La primera forma de identificar los elementos es por su nombre. Puede que los recuerdes como 'tags' de la sección de HTML. Cosas como `a`, `h1`, y `body` son algunos ejemplos de nombres de elementos. También podemos identificar elementos por el atributo `class` o el atributo `id`. Los valores de "class" e "id" son nombres que das al elemento para poderlo identificar. Con el atributo "class" identificamos grupos de elementos del mismo tipo y con el atributo "id" identificamos un elemento específico. For example, you could identify the following element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +Si quieres aprender más sobre los selectores CSS puedes consultar en [Selectores de CSS en w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +También necesitamos decirle a nuestra plantilla HTML que hemos añadido código CSS. Abre el archivo `blog/templates/blog/post_list.html` en el editor de código y añade esta línea al principio del todo: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +Aquí solo estamos cargando archivos estáticos. :) Entre las etiquetas `` y ``, después de los enlaces a los archivos CSS de Bootstrap, añade esta línea: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +El navegador lee los archivos en el orden que le son dados, por lo que debemos asegurarnos de que está en el lugar correcto. De lo contrario, el código en nuestro archivo podría ser reemplazado por código en nuestros archivos Bootstrap. Le acabamos de decir a nuestra plantilla dónde se encuentra nuestro archivo CSS. + +Ahora tu archivo debe tener este aspecto: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +De acuerdo, ¡guarda el archivo y actualiza el sitio! + +![Figura 14.2](images/color2.png) + +¡Buen trabajo! ¿Tal vez nos gustaría también dar un poco de aire a nuestro sitio web y aumentar el margen en el lado izquierdo?. ¡Vamos a intentarlo! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +Añade esto a tu CSS, guarda el archivo y ¡mira cómo funciona! + +![Figura 14.3](images/margin2.png) + +¿Quizá podríamos personalizar la tipografía del título? Pega esto en la sección `` del archivo `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Como antes, revisa el orden y pon antes del enlace a `blog/static/css/blog.css`. Esta línea importará un estilo de letra llamada *Lobster* de Google Fonts (https://www.google.com/fonts). + +Encuentra el bloque de declaración (el código entre las llaves `{` y `}`) `h1 a` en el archivo CSS `blog/static/css/blog.css`. Ahora añade la línea `font-family: 'Lobster';` entre las llaves y actualiza la página: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figura 14.3](images/font.png) + +¡Genial! + +Como ya hemos dicho, CSS tiene un concepto de clases. Las clases te permiten dar un nombre a una parte del código HTML para aplicar estilos solo a esta parte, sin afectar a otras. ¡Esto puede ser súper útil! Quizá tienes dos divs haciendo algo diferente (como el encabezado y el texto de tu publicación). Las clases pueden ayudarte a asignarles estilos distintos. + +Go ahead and name some parts of the HTML code. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Ahora añadiremos bloques de declaración a varios selectores. Los selectores que comienzan con `.` hacen referencia a clases. Hay muchos tutoriales y explicaciones excelentes sobre CSS en la Web que te pueden ayudar a entender el código que sigue a continuación. Por ahora, copia y pega lo siguiente en tu archivo `blog/static/css/blog.css`: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Luego rodea el código HTML que muestra los posts con declaraciones de clases. Cambia esto: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Guarda estos archivos y recarga tu sitio. + +![Figura 14.4](images/final.png) + +¡Woohoo! Queda genial, ¿Verdad? Mira el código que acabamos de pegar para encontrar los lugares donde añadimos clases en el HTML y las usamos en el CSS. ¿Qué cambiarías si quisieras que la fecha fuera color turquesa? + +No tengas miedo a experimentar con este CSS un poco y tratar de cambiar algunas cosas. Jugar con el CSS te puede ayudar a entender lo que hacen las distintas secciones. Si algo deja de funcionar, no te preocupes, ¡siempre puedes deshacerlo! + +Realmente recomendamos hacer cursos gratuitos online de "básico HTML & HTML5" y "CSS básico" en [freeCodeCamp](https://learn.freecodecamp.org/). Pueden ayudarte a aprender todo acerca de hacer tus sitios web más bonitos con HTML y CSS. + +¡¿Lista para el siguiente capítulo?! :) \ No newline at end of file diff --git a/es-ES/deploy/README.md b/es-ES/deploy/README.md new file mode 100644 index 00000000000..6c05d6fcc80 --- /dev/null +++ b/es-ES/deploy/README.md @@ -0,0 +1,246 @@ +# ¡Despliega! + +> **Nota** El siguiente capítulo puede ser, a veces, un poco difícil de seguir. Ten paciencia y acábalo. El despliegue es una parte importante del proceso en el desarrollo de un sitio web. Este capítulo está a mitad del tutorial para que tu mentor pueda ayudarte a conseguir que tu sitio web esté online, algo que puede ser un poco complicado. Así, aunque se te acabe el tiempo, podrás terminar el tutorial por tu cuenta. + +Hasta ahora, tu sitio web sólo está disponible 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 sitio web. :) + +Como ya has aprendido, un sitio web tiene que estar en un servidor. Hay muchos proveedores de servidores disponibles en internet, nosotros vamos a usar [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere es gratuito para aplicaciones pequeñas que no tienen muchos visitantes, y con eso tendrás más que suficiente por ahora. + +El otro servicio externo que vamos a utilizar es [GitHub](https://www.github.com), un servicio de almacenamiento de código. Hay otras opciones por ahí, pero hoy en día casi todas las programadoras y programadores tenemos una cuenta de GitHub, ¡y ahora tú también la vas a tener! + +Estos tres lugares serán importantes para ti. Tu ordenador local será el lugar donde desarrollas y pruebas. Cuando estés contento con los cambios, subirás una versión de tu programa a GitHub. Tu sitio web estará en PythonAnywhere y para actualizarlo descargarás la última versión de tu código desde GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Crear nuestro repositorio Git + +Git sigue los cambios realizados a un grupo determinado de archivos en lo que llamamos un repositorio de código (abreviado "repo"). Vamos a crear uno para nuestro proyecto. Abre la consola y ejecuta los siguientes comandos en el directorio de `djangogirls`: + +> **Nota** Comprueba en qué directorio estás ahora mismo (es decir, 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`. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Tu nombre" + $ git config --global user.email tu@ejemplo.com + + +Inicializar el repositorio de git es algo que sólo tenemos que hacer una vez por proyecto (y no tendrás que volver a teclear tu nombre de usuario y correo electrónico nunca más). + +Git llevará un seguimiento de los cambios realizados en todos los archivos y carpetas en este directorio, pero hay algunos archivos que queremos que ignore. Esto lo hacemos creando un archivo llamado `.gitignore` en el directorio base. Abre tu editor y crea un nuevo archivo con el siguiente contenido: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +Y guárdalo como `.gitignore` en la carpeta "djangogirls". + +> **Nota** ¡El punto al principio del nombre del archivo es importante! Si tienes problemas para crearlo (a los Mac no les gusta que crees ficheros con un punto al principio del nombre usando el Finder por ejemplo), entonces usa la opción "Save As" o "Guardar como" de tu editor, esto funcionará seguro. Asegúrate de no añadir `.txt`, `.py`, o ninguna otra extensión al nombre de fichero -- Git solo lo reconocerá si se llama exactamente `.gitignore`, sin nada más. Linux y MacOS usan archivos con nombres que comienzan con `.` (como `.gitignore`) y aparecen ocultos, por lo que el comando normal `ls` no te mostrará esos archivos. En su lugar, usa `ls -a` para ver el archivo `.gitignore`. +> +> **Nota** Uno de los archivos especificados en tu `.gitignore` es `db.sqlite3`. Ese fichero es tu base de datos local, donde se almacenan los usuarios y publicaciones de tu blog. Vamos a seguir las buenas prácticas de programación web: vamos a usar bases de datos separadas para tu sitio local y tu sitio en producción en PythonAnywhere. La base de datos en PythonAnywhere podría ser SQLite, como en tu máquina de desarrollo, pero también podrías usar otro gestor de base de datos como MySQL o PostgreSQL que pueden soportar muchas más visitas que SQLite. En cualquier caso, al ignorar la base de datos SQLite en tu copia de GitHub, todos los posts y el super usuario que has creado hasta el momento solo estarán disponibles en local, y tendrás que crear nuevos usuarios y publicaciones en producción. Tu base de datos local es un buen campo de pruebas donde puedes probar diferentes cosas sin miedo a estropear o borrar las publicaciones reales de tu blog. + +Te recomendamos utilizar el comando `git status` antes de `git add` o en cualquier momento en que no sepas muy bien lo que ha cambiado. Esto te ayudará a evitar sorpresas, como subir cambios o archivos que no queríamos subir. El comando `git status` muestra información sobre cualquier archivo no seguido ("untracked"), modificado ("modified"), preparado ("staged"), el estado de la rama y muchas cosas más. La salida debería ser parecida a esto: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +Y finalmente guardamos nuestros cambios. Ve a la consola y ejecuta estos comandos: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Subiendo tu código a Github + +Vaya a [GitHub.com](https://www.github.com) y regístrese para obtener una cuenta de usuario nueva y gratuita. (Si ya lo hiciste en la preparación del taller, ¡eso es genial!) Asegúrate de recordar tu contraseña (agrégala a tu administrador de contraseñas, si usas uno). + +A continuación, crea un nuevo repositorio con el nombre "my-first-blog". Deja el checkbox "initialize with a README" sin marcar, deja la opción de .gitignore vacía (ya lo hemos hecho manualmente) y deja la licencia como None. + +![](images/new_github_repo.png) + +> **Nota** El nombre `my-first-blog` es importante - podrías escoger otro, pero va a salir muchas veces en las instrucciones que vienen a continuación, y vas a tener que acordarte de cambiarlo cada vez. Lo más fácil es quedarse con el nombre `my-first-blog`. + +En la siguiente pantalla, verás la URL para clonar el repo, que tendrás que usar en los comandos que van a continuación: + +![](images/github_get_repo_url_screenshot.png) + +Ahora necesitas enlazar el repositorio Git en tu ordenador con el repositorio de GitHub. + +Escribe lo siguiente en la consola (cambia `` por tu nombre de usuario de GitHub, pero sin los símbolos < y > -- fíjate en que la URL debería coincidir con la URL para clonar el repo que acabas de ver): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Cuando hagas push a GitHub, te preguntará tu usuario y password de GitHub, y después de introducirlos, deberías ver algo como esto: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Tu código ya está subido a GitHub. ¡Ve y compruébalo! Encontrarás que está en buena compañía - [Django](https://github.com/django/django), [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial) y muchos otros proyectos de software libre están alojados en GitHub. :) + +# Configurar nuestro blog en PythonAnywhere + +## Crea una cuenta en PythonAnywhere + +> **Nota** A lo mejor ya has creado una cuenta en PythonAnywhere durante los pasos de instalación. Si es así, no necesitas hacerlo otra vez. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configurar nuestro sitio en PythonAnywhere + +Vuelve al [dashboard de PythonAnywhere](https://www.pythonanywhere.com/) haciendo click en el logo, y escoge la opción de iniciar una consola "Bash" – esta terminal es como la que hay en tu ordenador, pero en el servidor de PythonAnywhere. + +![La sección 'New Console' en la interfaz de PythonAnywhere con un botón para 'bash'](images/pythonanywhere_bash_console.png) + +> **Nota** PythonAnywhere está basado en Linux, así que si estás en Windows, la consola será un poco distinta a la de tu ordenador. + +Para desplegar una aplicación web en PythonAnywhere necesitas descargar tu código de GitHub y configurar PythonAnywhere para que lo reconozca y lo sirva como una aplicación web. Hay formas de hacerlo manualmente, pero PythonAnywhere tiene una herramienta automática que lo hará todo por nosotros. Lo primero, vamos a instalar la herramienta: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +Eso debería mostrar en pantalla algunos mensajes como `Collecting pythonanywhere`, y finalmente una linea diciendo que ha terminado bien: `Successfully installed (...) pythonanywhere- (...)`. + +Ahora ejecutaremos el asistente para configurar automáticamente nuestra aplicación desde GitHub. Teclea lo siguiente en la consola de PythonAnywhere (no te olvides de usar tu propio nombre de usuario de GitHub en lugar de ``, para que la URL sea como la URL de clonar el repo de GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +A medida que se ejecuta, podrás ver lo que hace: + +- Se descarga tu código de GitHub +- Crear un virtualenv en PythonAnywhere, como el de tu propia computadora +- Actualiza tus ficheros de settings con algunos settings de despliegue +- Crea la base de datos en PythonAnywhere ejecutando el comando `manage.py migrate` +- Configura los archivos estáticos (static) (luego hablaremos de éstos con más detalle) +- Y configura PythonAnywhere para publicar tu aplicación web a través de su API + +En PythonAnywhere todos estos pasos están automatizados, pero son los mismos que tendrías que seguir en cualquier otro proveedor de servidores. + +Lo más importante que debes notar en este momento es que tu base de datos en PythonAnywhere está totalmente separada de tu base de datos en tu propia computadora, por lo que puedes tener diferentes publicaciones y cuentas de administrador. Como consecuencia, igual que lo hicimos en tu ordenador, tenemos que crear la cuenta de administrador con el comando `createsuperuser`. PythonAnywhere ya ha activado el virtualenv automáticamente, así que lo único que tienes que hacer es ejecutar: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Teclea las credenciales para tu usuario admin. Para evitar confusiones, te recomendamos usar el mismo nombre de usuario que usaste en tu ordenador local; aunque a lo mejor prefieres que la contraseña en PythonAnywhere sea más segura. + +Ahora, si quieres, también puedes ver tu código en PythonAnywhere con el comando `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +También puedes ir a la página de ficheros ("Files") y navegar por los ficheros y directorios usando el visor de PythonAnywhere. (Desde la página de la consola ("Console"), puedes ir a cualquier otra página de PythonAnywhere usando el botón de la esquina superior derecha. Desde el resto de páginas, también hay enlaces a las otras en la parte superior.) + +## ¡Ya estás en vivo! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Nota** Este es un tutorial para principiantes, y al desplegar este sitio hemos tomado algunos atajos que tal vez no sean las mejores prácticas desde el punto de vista de la seguridad. Si decide construir sobre este proyecto, o comenzar un nuevo proyecto, debe revisar la [lista de verificación de despliegue de Django](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) para obtener algunos consejos sobre cómo proteger su sitio. + +## Consejos de depuración + +Si te sale un error al ejecutar el script `pa_autconfigure_django.py`, aquí hay algunas causas comunes: + +- Te has olvidado de crear el token de API de PythonAnywhere. +- No has puesto bien la URL de GitHub +- Si ves un error diciendo *"Could not find your settings.py*, es probable que no añadieras todos tus archivos a Git, y/o no los subiste a GitHub correctamente. Repasa la sección de Git más arriba +- Si anteriormente se suscribió a una cuenta de PythonAnywhere y tuvo un error con collectstatic, probablemente tenga una versión anterior de SQLite (por ejemplo, 3.8.2) para su cuenta. En ese caso, regístrese para una nueva cuenta e intente los comandos en la sección PythonAnywhere anterior. + +Si ves un error al visitar tu sitio, el primer lugar para ver qué está pasando es el **log de errores**. Encontrará un enlace en la página ["Web"](https://www.pythonanywhere.com/web_app_setup/) de PythonAnywhere. Mira si hay algún mensaje de error allí; los más recientes están en la parte inferior. + +Hay también algunos [ consejos generales de depuración en la página de ayuda de PythonAnywhere](http://help.pythonanywhere.com/pages/DebuggingImportError). + +Y recuerda, ¡tu mentor está aquí para ayudar! + +# ¡Comprueba tu página! + +La página por defecto debería decir "It worked!", tal como dice en tu ordenador local. Prueba a añadir `/admin/` al final de la URL y llegarás a la página de administración. Entra con tu usuario y password, y verás que puedes añadir nuevas publicaciones en el servidor -- recuerda, los post que tenías en tu base de datos local no se han subido a al blog publicado en producción. + +Después de crear algunas publicaciones, puedes volver a tu instalación local (no la de PythonAnywhere). A partir de ahora, trabaja en tu instalación local para hacer los siguientes cambios. Este es un flujo de trabajo típico en el desarrollo web – haz cambios localmente, sube (push) esos cambios a GitHub, y descarga (pull) tus cambios al servidor de publicación. Esto te permite trabajar y experimentar en local sin romper tu página publicada. Mola, ¿eh? + +¡Date una *GRAN* palmada en la espalda! Desplegar a un servidor es una de las partes más complicadas de desarrollo web y a menudo la gente necesita varios días para que funcione del todo. Pero tu ya tienes tu sitio publicado, ¡en internet de verdad! \ No newline at end of file diff --git a/es-ES/deploy/install_git.md b/es-ES/deploy/install_git.md new file mode 100644 index 00000000000..d9e3b5c5e62 --- /dev/null +++ b/es-ES/deploy/install_git.md @@ -0,0 +1,52 @@ +Git es un "sistema de control de versiones" que utilizan muchos programadores. Este software puede seguir los cambios realizados en archivos a lo largo del tiempo de forma que más tarde puedas volver a cualquier versión anterior. Algo similar a la herramienta de "Control de Cambios" en los programas de tipo Word (por ejemplo, Microsoft Word o LibreOffice Writer), pero mucho más potente. + +## Instalar Git + + + +Puedes descargar Git desde [git-scm.com](https://git-scm.com/). Puedes hacer click en "Next" en todos los pasos excepto en dos: cuando se te pregunte que selecciones tu editor, selecciona Nano, y en el paso "adjusting your PATH environment", selecciona "Use Git and optional Unix tools from the Windows Command Prompt" (la última opción). Aparte de eso, los valores por defecto son correctos. "Checkout Windows-style, commit Unix-style line endings" tampoco necesita corrección. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Descarga Git de [git-scm.com](https://git-scm.com/) y sigue las instrucciones. + +> **Nota** Si estas usando OS X 10.6, 10.7 o 10.8, tendrás que instalar git desde aquí: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$sudo zypper install git +``` + + \ No newline at end of file diff --git a/es-ES/deploy/signup_pythonanywhere.md b/es-ES/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..2ba4197a81d --- /dev/null +++ b/es-ES/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere es un servicio para ejecutar código Python en servidores "en la nube". Lo vamos a usar para alojar nuestro sitio para que esté disponible en Internet. + +Almacenaremos del blog que estamos construyendo sobre Python Anywhere. Crea una cuenta como "Principiante/Beginner" en Python Anywhere (el modo gratuito esta bien, no necesitas una tarjeta de crédito). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![La pagina de entrada de Python Anywhere muestra el botón para crear una cuenta "Principiante"](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Nota** Cuando elijas un nombre de usuario, recuerda que la URL de tu blog tendrá la forma `tunombredeusuario.pythonanywhere.com`, así que lo mejor será usar tu apodo o elegir un nombre que indique de qué trata tu blog. Asegúrate también de recordar tu contraseña (añádela a tu gestor de contraseñas, si usas uno). + +## Crear un token para la API de PythonAnywhere + +Este paso solo necesita ser completado una vez. Una vez que te hayas registrado en PythonAnywhere, serás llevado a tu tablón principal. Encontrarás el enlace a la página de tu "Cuenta" en la esquina superior derecha: + +![Enlace de cuenta en la parte superior derecha de la pagina](../deploy/images/pythonanywhere_account.png) + +Después selecciona la lengueta llamada "API token", y haz click en el botón que dice "Crear nueva API token" + +![Lengüeta de la API token en la pagina de cuenta](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/es-ES/django/README.md b/es-ES/django/README.md new file mode 100644 index 00000000000..110fd6ec950 --- /dev/null +++ b/es-ES/django/README.md @@ -0,0 +1,27 @@ +# ¿Qué es Django? + +Django (*gdh/ˈdʒæŋɡoʊ/jang-goh*) es un framework de aplicaciones web gratuito y de código abierto (open source) escrito en Python. Un framework web es un conjunto de componentes que te ayudan a desarrollar sitios web más fácil y rápidamente. + +Cuando construyes un sitio web, siempre 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 nosotros, hace tiempo que otros desarrolladores se dieron cuenta de que siempre se enfrentaban a los mismos problemas cuando construían sitios web, y por eso se unieron y crearon frameworks (Django es uno de ellos) con componentes listos para usarse. + +Los frameworks sirven para que no tengamos que reinventar la rueda cada vez y que podamos avanzar más rápido al construir un nuevo sitio. + +## ¿Por qué necesitas un framework? + +Para entender para que sirve realmente Django, necesitamos fijarnos en cómo funcionan los servidores. Lo primero es que el servidor necesita enterarse de que tu quieres que te sirva una página web. + +Imagina un buzón (puerto) en el que alguien está constantemente mirando si hay cartas entrantes (peticiones). Esto es lo que hace un servidor web. El servidor web lee la carta, y envía una respuesta con la página web. Pero para enviar algo, tenemos que tener algún contenido. Y Django nos ayuda a crear ese contenido. + +## ¿Qué sucede cuando alguien solicita una página web de tu servidor? + +Cuando llega una petición a un servidor web, es pasada a Django quien intenta averiguar que es realmente solicitado. Toma primero una dirección de página web e intenta 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 hacer coincidir 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 *view (vista)*). + +Imagina a un cartero llevando una carta. Él está caminando por la calle y comprueba cada número de casa con el que está en la carta. Si coincide, deja la carta allí. Así es como funciona el urlresolver! + +En la función de *view (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 tienes permiso para hacerlo, actualizar la descripción de tu trabajo y devolver un mensaje: "¡Hecho!". Luego la *vista* genera una respuesta y Django puede enviarla al navegador del usuario. + +Esta descripción es un poco simplista, pero de momento no necesitas saber todos los detalles técnicos, con tener una idea general es más que suficiente. + +Así que en lugar de detenernos demasiado en los detalles, vamos a empezar a crear algo con Django y ¡así aprenderemos las cosas importantes sobre la marcha! \ No newline at end of file diff --git a/es-ES/django_admin/README.md b/es-ES/django_admin/README.md new file mode 100644 index 00000000000..ff8a68dfb8c --- /dev/null +++ b/es-ES/django_admin/README.md @@ -0,0 +1,57 @@ +# Administrador de Django + +Para agragar, editar y borrar los posts que hemos modelado, usaremos el administrador (admin) de Django. + +Abre el fichero `blog/admin.py` en el editor y reemplaza su contenido con esto: + +{% filename %}blog/admin.py{% endfilename %} + +```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)`. + +Ok, es hora de ver nuestro modelo Post. Recuerda ejecutar `python manage.py runserver` en la consola para correr el servidor web. Ve a tu navegador y escribe la dirección http://127.0.0.1:8000/admin/. Veras una página de inicio de sesión como esta: + +![Página de inicio de sesión](images/login_page2.png) + +Para iniciar sesión, deberás crear un *superusuario (superuser)*, que es un usuario que tiene control sobre todo el sitio. Vuelve a la línea de comandos, escribe `python manage.py createsuperuser` y pulsa enter. + +> Recuerda, para escribir comandos mientras el servidor web esta funcionando, abre una nueva terminal y activa el virtualenv. Revisamos como escribir nuevos comandos en el capitulo **Tu primer proyecto de Django!**, al inicio de la sección **Iniciando el servidor web**. + +{% filename %}Mac OS X o Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +Cuando te lo pida, escribe tu nombre de usuario (en minúscula, sin espacios), email y contraseña. **No te preocupes si no puedes ver la password que estás tecleando - así es como debe ser.** Tecléalo y pulsa `intro` para continuar. Luego, verás algo así (Donde username y email serán los que escribiste anteriormente): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Vuelve a tu navegador. Entra con las credenciales de super usuario que tu escogiste; verás el panel de administrador de Django. + +![Administrador de Django](images/django_admin3.png) + +Ve a 'Posts' y curiosea un poco. Añade cinco o seis publicaciones en tu blog. No te preocupes por el contenido -- solo será visible para tí en tu ordenador -- puedes copiar y pegar texto de este tutorial para ir más rápido. :) + +Asegúrate de que al menos dos o tres posts (pero no todos) tengan la fecha de publicación definida. Esto será muy poderoso después. + +![Administrador de Django](images/edit_post3.png) + +Si desea saber más sobre el administrador de Django, debe consultar la documentación de Django: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +Este posiblemente sea un buen momento para tomar un café (o te) o algo para comer y re energizar tu cuerpo. Has creado tu primer modelo en Django - ¡Mereces un pequeño descanso! \ No newline at end of file diff --git a/es-ES/django_forms/README.md b/es-ES/django_forms/README.md new file mode 100644 index 00000000000..7a7057981a3 --- /dev/null +++ b/es-ES/django_forms/README.md @@ -0,0 +1,479 @@ +# Formularios de Django + +Lo último que haremos en nuestro sitio web será crear una forma agradable de agregar y editar posts en el blog. El `admin` de Django 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 los formularios de Django es que podemos definirlos desde cero o crear un `ModelForm`, el cual guardará el resultado del formulario en el modelo. + +Esto es exactamente lo que queremos hacer: crearemos un formulario para nuestro modelo `Post`. + +Como cada parte importante de Django, los formularios tienen su propio archivo: `forms.py`. + +Necesitamos crear un archivo con este nombre en el directorio `blog`. + + blog + └── forms.py + + +Vale, ábrelo en el editor de código y teclea lo siguiente: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Lo primero, necesitamos importar Django forms (`from django import forms`) y nuestro modelo `Post` (`from .models import Post`). + +`PostForm`, como probablemente sospechas, es el nombre de nuestro formulario. Necesitamos decirle a Django que este formulario es un `ModelForm` (así Django hará algo de magia por nosotros) - `forms.ModelForm` es responsable de ello. + +Luego, tenemos `class Meta`, donde le decimos a Django que modelo debe ser utilizado para crear este formulario (`model = Post`). + +Finalmente, podemos decir que campo(s) deberían estar en nuestro formulario. En este escenario sólo queremos `title` y `text` para ser mostrados - `author` será la persona que esta conectada (¡tú!) y `created_date` se definirá automáticamente cuando creemos un post (es decir, en el código), ¿cierto? + +¡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 + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## Vista post_new + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Plantilla + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* Tenemos que mostrar el formulario. Podemos hacerlo, por ejemplo, con un sencillo {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* Necesitamos un botón `Guardar`. Lo hacemos con un botón HTML: ``. +* Finalmente justo después de abrir la etiqueta `
` tenemos que añadir {% raw %}`{% csrf_token %}`{% endraw %}. ¡Esto es muy importante ya que hace que tus formularios sean seguros! Si olvidas este pedazo, Django se molestará cuando intentes guardar el formulario: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Guardar el formulario + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Validación de formularios + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Editar formulario + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Botón "Editar"](images/edit_button2.png) + +Cuando hagas clic en él, verás el formulario con nuestra publicación de blog: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Seguridad + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## Una cosa más: ¡Tiempo de despliegue! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* Lo primero, haz commit de tus últimos cambios y súbelo (push) a GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Luego, en una [consola Bash de PythonAnywhere](https://www.pythonanywhere.com/consoles/) + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Para terminar ve a ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (usa el botón del menú de la esquina superior derecha, encima de la consola) y haz click en **Reload**. Recarga tu https://subdomain.pythonanywhere.com blog para ver los cambios. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/es-ES/django_installation/README.md b/es-ES/django_installation/README.md new file mode 100644 index 00000000000..5e540787896 --- /dev/null +++ b/es-ES/django_installation/README.md @@ -0,0 +1,7 @@ +# Instalacion de Django + +> **Nota** Si usas un Chromebook, omite este capítulo y asegúrate de seguir las instrucciones de [Chromebook Setup](../chromebook_setup/README.md). +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/es-ES/django_installation/instructions.md b/es-ES/django_installation/instructions.md new file mode 100644 index 00000000000..e4de5cd18ee --- /dev/null +++ b/es-ES/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Parte de esta sección está basada en tutoriales por Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parte de este capítulo está basada en el [django-marcador tutorial](http://django-marcador.keimlink.de/) bajo la licencia Creative Commons Attribution-ShareAlike 4.0 internacional. El tutorial de django-marcador tiene derechos de autor de Markus Zapke-Gündemann et al. + +## Entorno virtual + +Antes de instalar Django, instalaremos una herramienta extremadamente útil que ayudará a mantener tu entorno de desarrollo ordenado en tu computadora. Es posible saltarse este paso, pero es altamente recomendable. ¡Empezar con la mejor configuración posible te ahorrará muchos problemas en el futuro! + +Así que, vamos a crear un **entorno virtual** (también llamado un *virtualenv*). Virtualenv aísla tu configuración de Python/Django por cada proyecto. Esto quiere decir que cualquier cambio que hagas en un sitio web no afectará a ningún otro que estés desarrollando. Genial, ¿no? + +Todo lo que necesitas hacer es encontrar un directorio en el que quieras crear el `virtualenv`; tu directorio home, por ejemplo. En Windows, puede verse como `C:\Users\Name` (donde `Name` es el nombre de tu usuario). + +> **NOTA:** En Windows, asegúrate de que este directorio no contiene caracteres especiales o acentuados; si tu nombre de usuario contiene caracteres acentuados, usa un directorio distinto, por ejemplo `C:\djangogirls`. + +Para este tutorial usaremos un nuevo directorio `djangogirls` en tu directorio home: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +Haremos un virtualenv llamado `myvenv`. El comando general estará en el formato: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +Para crear un nuevo `virtualenv`, necesitas abrir una terminal "command prompt" y ejecutar `python -m venv myvenv`. Se verá así: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Donde `myvenv` es el nombre de tu `virtualenv`. Puedes utilizar cualquier otro nombre, pero asegúrate de usar minúsculas y no usar espacios, acentos o caracteres especiales. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +Podemos crear un `virtualenv` en Linux y OS X, es tan sencillo como ejecutar `python3 -m venv myvenv`. Se verá así: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` es el nombre de tu `virtualenv`. Puedes usar cualquier otro nombre, pero sólo utiliza minúsculas y no incluyas espacios. También es una buena idea mantener el nombre corto. ¡Vas a referirte muchas veces a él! + +> **NOTA:** En algunas versiones de Debian/Ubuntu, puede que obtengas el siguiente error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. En sistemas Debian/Ubuntu, tendrás que instalar el paquete python3-venv usando el siguiente comando. +> apt-get install python3-venv +> Puede que tengas que usar sudo con este comando. Después de instalar el paquete python3-venv, vuelve a crear tu entorno virtual. +> +> +> En este caso, sigue las instrucciones anteriores e instala el paquete `python3-venv`: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTA:** En algunas versiones de Debian/Ubuntu inicializar el entorno virtual de esta manera da el siguiente error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Para evitar esto, utiliza directamente el comando `virtualenv`. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTA:** Si obtienes un error como +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> entonces ejecuta: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Trabajar con virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Inicia el entorno virtual ejecutando: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. En este caso, abre otro Windows PowerShell con la opción "Ejecutar como administrador". Luego intenta escribir el siguiente comando antes de inicializar tu entorno virtual: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32 > Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> La ventaja es que tu no tienes que cambiar las ventanas entre el editor de código y la línea de comandos + + + + + +Inicia el entorno virtual ejecutando: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +¡Recuerda reemplazar `myvenv` con tu nombre de `virtualenv` que hayas elegido! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +Sabrás que tienes `virtualenv` iniciado cuando veas que la línea de comando en tu consola tiene el prefijo `(myvenv)`. + +Cuando trabajes en un entorno virtual, `python` automáticamente se referirá a la versión correcta, de modo que puedes utilizar `python` en vez de `python3`. + +Ok, tenemos todas las dependencias importantes en su lugar. ¡Finalmente podemos instalar Django! + +## Instalar Django {#django} + +Ahora que tienes tu `virtualenv` iniciado, puedes instalar Django. + +Antes de hacer eso, debemos asegurarnos que tenemos la última versión de `pip`, el software que utilizamos para instalar Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Instalar paquetes con un fichero de requisitos (requirements) + +Un fichero de requisitos (requirements) tiene una lista de dependencias que se deben instalar mediante `pip install`: + +Primero crea un archivo `requirements.txt` dentro de tu directorio `djangogirls`, usando el editor de código que instalaste previamente. Lo puedes hacer mediante abriendo un nuevo archivo en el editor de código y guardandolo como `requirements.txt` en el directorio `djangogirls`. Tu directorio se verá así: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +Dentro del fichero `djangogirls/requirements.txt` deberías tener el siguiente texto: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Ahora, ejecuta `pip install -r requirements.txt` para instalar Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). Si los tiene, por favor considera usar otro lugar sin espacios, acentos o caracteres especiales (sugerencia: `C:\djangogirls`). Crea un nuevo virtualenv en el nuevo directorio, luego borra el viejo y trata de escribir el comando anterior otra vez. (Moviendo el directorio virtualenv no funcionará debido a que usa rutas absolutas.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> Si tu obtienes un error cuando llamas pip en Ubuntu 12.04, por favor corre `python -m pip install -U --force-reinstall pip` para reparar la instalación de pip en el virtualenv. + + + +¡Eso es todo! Ahora estás lista (por fin) para crear una aplicación Django! \ No newline at end of file diff --git a/es-ES/django_models/README.md b/es-ES/django_models/README.md new file mode 100644 index 00000000000..3280cc34823 --- /dev/null +++ b/es-ES/django_models/README.md @@ -0,0 +1,203 @@ +# Modelos en Django + +Lo que queremos crear ahora es algo que almacene todas las entradas de nuestro blog. Pero para poder hacerlo tenemos que hablar un poco sobre algo llamado `objetos`. + +## Objetos + +Hay un concepto en el mundo de la programación llamado `programación orientada a objetos`. La idea es que en lugar de escribir todo como una aburrida secuencia de instrucciones de programación podemos modelar cosas y definir cómo interactúan entre ellas. + +Entonces, ¿qué es un objeto? Es un conjunto de propiedades y acciones. Suena raro, pero te daremos un ejemplo. + +Si queremos modelar un gato crearemos un objeto `Gato` que tiene algunas propiedades como: `color`, `edad`, `temperamento` (como bueno, malo, o dormilón ;)), y `dueño` (este es un objeto `Persona` o en caso de un gato callejero, esta propiedad está vacía). + +Luego, el `Gato` tiene algunas acciones como: `ronronear`, `arañar` o `alimentar` (en cuyo caso daremos al gato algo de `ComidaDeGato`, el cual debería ser un objeto aparte con propiedades como `sabor`). + + 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`). + +Y ahora, ¿cómo modelamos las entradas en el blog? Queremos construir un blog, ¿no? + +Necesitamos responder a la pregunta: ¿Qué es una entrada de un blog? ¿Qué propiedades debería tener? + +Bueno, seguro que nuestras entradas de blog 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 se creó y publicó la entrada. + + 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 lograr, ¡podemos empezar a modelarlo en Django! + +## Modelos en Django + +Sabiendo qué es un objeto, podemos crear un modelo en Django para nuestros entradas de blog. + +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. Es un lugar en el cual almacenarás la información sobre usuarios, tus entradas de blog, etc. Utilizaremos una base de datos SQLite para almacenar nuestros datos. Este es el adaptador de base de datos predeterminado en Django -- será suficiente para nosotros por ahora. + +Puedes pensar el modelo en la base de datos, como una hoja de cálculo con columnas (campos) y filas (datos). + +### Crear 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 de la carpeta de `djangogirls` donde está el archivo `manage.py`): + +{% filename %}Mac OS X y Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +Notarás que se ha creado un nuevo directorio `blog` y ahora contiene una cantidad de archivos. Los directorios y archivos en nuestro proyecto deberían verse así: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +Después de crear una aplicación, también necesitamos decirle a Django que debe utilizarla. Eso se hace en el fichero `mysite/settings.py` -- ábrelo en el editor. Tenemos que encontrar `INSTALLED_APPS` y agregar una línea que contiene `'blog.apps.BlogConfig',` justo por encima de `]`. El producto final debe tener este aspecto: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Crear el modelo del Post + +En el archivo `blog/models.py` definimos todos los objetos llamados `Models`. Este es un lugar en el cual definiremos nuestra entrada del blog. + +Abre `blog/models.py` en el editor, borra todo, y escribe código como este: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User', on_delete=models.CASCADE) + 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 +``` + +> Comprueba nuevamente que usas dos guiones bajos (`_`) en cada lado de `str`. Esta convención se usa en Python con mucha frecuencia y a veces también se llaman "dunder" (abreviatura de "double-underscore" o, en español, "doble guión bajo"). + +Da un poco de miedo, ¿no? Pero no te preocupes, ¡vamos a explicar qué significan estas líneas! + +Todas las líneas que comienzan con `from` o `import` son líneas para agregar 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 línea define nuestro modelo (es un `objeto`). + +- `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). Siempre inicia el nombre de una clase con una letra 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 de las que hablábamos: `title`, `text`, `created_date`, `published_date` y `author`. Para ello tenemos que definir el tipo de cada campo (¿es texto? ¿un número? ¿una fecha? ¿una relación con otro objeto como un User (usuario)?) + +- `models.CharField`, así es como defines un texto con un número limitado de caracteres. +- `models.TextField`, este es para texto largo sin límite. Suena perfecto para el contenido de la entrada del blog, ¿no? +- `models.DateTimeField`, este es fecha y hora. +- `modelos.ForeignKey`, este es una relación (link) con otro modelo. + +No vamos a explicar aquí cada pedacito de código porque nos tomaría demasiado tiempo. Debería echar un vistazo a la documentación de Django si desea obtener más información sobre los campos Modelo y cómo definir otras cosas distintas a las descritas anteriormente (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +¿Y qué sobre `def publish(self):`? Es exactamente el método `publish` que mencionábamos antes. `def` significa que es una función/método y `publish` es el nombre del método. Puedes cambiar el nombre del método, si quieres. La regla de nomenclatura es utilizar minúsculas y guiones bajos en lugar de espacios. Por ejemplo, un método que calcule el precio medio se podría llamar `calcular_precio_medio`. + +Los métodos suelen devolver (`return`, en inglés) algo. Hay un ejemplo de esto en el método `__str__`. En este escenario, cuando llamemos a `__str__()` obtendremos un texto (**string**) con un título de Post. + +También, nota que ambos `def publish(self):`, y `def __str__(self):` son indentados dentro de nuestra clase. Porque Python es sensible a los espacios en blancos, necesitamos indentar nuestros métodos dentro de la clase. De lo contrario, los métodos no pertenecen a la clase, y puedes obtener un comportamiento inesperado. + +Si algo todavía no está claro sobre modelos, ¡no dudes en preguntar a tu guía! Sabemos que es complicado, sobre todo cuando aprendes lo que son funciones y objetos al mismo tiempo. Pero 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 aquí es agregar nuestro nuevo modelo a la base de datos. Primero tenemos que hacer saber a Django que hemos hecho cambios en nuestro modelo. (Lo acabamos de crear!) Ve a tu terminal y escribe `python manage.py makemigrations blog`. Se verá así: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Nota:** Recuerda guardar los archivos que edites. De otro modo, tu computador ejecutara las versiones anteriores lo que puede ocasionar errores inesperados. + +Django preparó un archivo de migración que ahora tenemos que aplicar a nuestra base de datos. Escribe `python manage.py migrate blog` y el resultado debería ser: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +¡Hurra! ¡Nuestro modelo Post ya está en nuestra base de datos! Estaría bien verlo, ¿no? ¡Salta al siguiente capítulo para ver qué aspecto tiene tu Post! \ No newline at end of file diff --git a/es-ES/django_orm/README.md b/es-ES/django_orm/README.md new file mode 100644 index 00000000000..431c4474201 --- /dev/null +++ b/es-ES/django_orm/README.md @@ -0,0 +1,221 @@ +# ORM de Django y QuerySets + +En este capítulo aprenderás cómo Django se conecta a la base de datos y almacena los datos en ella. ¡Vamos a sumergirnos! + +## ¿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 la base de datos, filtrarlos y ordenarlos. + +Es más fácil de aprender con ejemplos. Vamos a intentarlo, ¿de acuerdo? + +## Django shell + +Abre tu consola local (no la de PythonAnywhere) y escribe este comando: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +El resultado debería ser: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +Ahora estás en la consola interactiva de Django. Es como una consola de Python normal, pero con un poco de magia de Django. :) Aquí también se pueden usar todos los comandos de Python. + +### Todos los objetos + +Vamos a mostrar todos nuestros posts primero. Puedes hacerlo con el siguiente comando: + +{% filename %}command-line{% endfilename %} + +```python +>>> 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 Post no existe. Esto es correcto, ¡olvidamos importarlo! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +Vamos a importar el modelo `Post` de `blog.models`. Y probamos de nuevo a mostrar todas las publicaciones (posts): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +¡Es la lista de posts que creamos anteriormente! Creamos estos posts usando la interfaz de administración de Django. Pero, ahora queremos crear nuevos posts usando Python, ¿cómo lo hacemos? + +### Crear objetos + +Esta es la forma de crear un nuevo objeto Post en la base de datos: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Pero nos falta un ingrediente aquí: `me`. Tenemos que pasar una instancia del modelo `User` como autor. ¿Eso cómo se hace? + +Primero importemos el modelo User: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +¿Qué usuarios tenemos en nuestra base de datos? Prueba esto: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +¡Este es el superusuario que hemos creado antes! Ahora, vamos a obtener una instancia de éste usuario (cambia el código para usar tu propio nombre de usuario): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +Como vés, ya hemos obtenido (`get`) un usuario (`User`) cuyo `username` es igual a 'ola'. ¡Mola! + +Ahora, finalmente, podemos crear nuestra entrada: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +¡Hurra! ¿Quieres probar si funcionó? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +¡Ahí está, una entrada de blog más en la lista! + +### Agrega más entradas + +Ahora puedes divertirte un poco y agregar más entradas para ver cómo funciona. Agrega dos o tres más y avanza a la siguiente parte. + +### Filtrar objetos + +Una parte importante de los QuerySets es la habilidad para filtrar los resultados. Digamos que queremos encontrar todos los post del usuario ola. Usaremos `filter` en vez de `all` en `Post.objects.all()`. Entre paréntesis estableceremos qué condición (o condiciones) debe cumplir un post del blog para aparecer como resultado 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 tiene este aspecto: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +¿O quizá queremos ver todas las entradas que contengan la palabra 'title' en el campo `title`? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Nota** Hay dos guiones bajos (`_`) entre `title` y `contains`. El ORM de Django utiliza esta sintaxis para separar los nombres de los campos ("title") de las operaciones o filtros ("contains"). Si sólo utilizas un guión bajo, obtendrás un error como "FieldError: Cannot resolve keyword title_contains". + +También puedes obtener una lista de todos los post publicados. Lo hacemos filtrando los post que tienen la fecha de publicación, `published_date`, en el pasado: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Por desgracia, el post que hemos añadido desde la consola de Python aún no está publicado. Pero lo podemos cambiar! Primero obtén una instancia de la entrada que queremos publicar: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +Y luego publícala con nuestro método `publish`: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Ahora vuelve a intentar obtener la lista de posts publicados (pulsa la tecla de "flecha arriba" tres veces y pulsa `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordenar objetos + +Los QuerySets también te permiten ordenar la lista de objetos. Intentemos ordenarlos por el campo `created_date`: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +También podemos invertir el orden agregando `-` al principio: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Consultas complejas a través de encadenamiento de métodos + +Como ves, algunos métodos en `Post.objects` devuelven un QuerySet. Los mismos métodos pueden ser llamados también en un QuerySet, y entonces devolverán un nuevo QuerySet. También puedes combinar QuerySets **encadenando** uno con otro: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +Es muy potente y te permite escribir consultas bastante complejas. + +¡Genial! ¡Ahora estás lista para la siguiente parte! Para cerrar la consola, escribe esto: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/es-ES/django_start_project/README.md b/es-ES/django_start_project/README.md new file mode 100644 index 00000000000..745e1af7ddb --- /dev/null +++ b/es-ES/django_start_project/README.md @@ -0,0 +1,261 @@ +# ¡Tu primer proyecto en Django! + +> Parte de este capítulo se basa en tutoriales por Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parte de este capítulo está basado en el [ tutorial django-marcador](http://django-marcador.keimlink.de/) 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. + +¡Vamos a crear un blog sencillo! + +El primer paso es iniciar un nuevo proyecto de Django. Básicamente, significa que vamos a lanzar unos scripts proporcionados por Django que nos crearán el esqueleto de un proyecto de Django. Son solo un montón de directorios y archivos que usaremos más tarde. + +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 buena idea. Django necesita mantener una cierta estructura para poder encontrar cosas importantes. + +> Recuerda ejecutar todo en el virtualenv. Si no ves un prefijo `(myvenv)` en tu consola tienes que activar tu virtualenv. Explicamos cómo hacerlo en el capítulo de **Instalación de Django** en la sección **Trabajar con virtualenv**. Basta con escribir `myvenv\Scripts\activate` en Windows o `source myvenv/bin/activate` en Mac OS / Linux. + + + +En MacOS o Linux deberías ejecutar el siguiente comando en la consola. **no te olvides de añadir el punto `.` al final** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> El punto `.` es crucial porque le dice al script que instale Django en el directorio actual (para el cual el punto `.` sirve de abreviatura). +> +> **Nota** Cuando escribas los comandos de arriba acuérdate de que sólo tienes que escribir la parte que empieza por `django-admin`. La parte de `(myvenv) ~/djangogirls$` que mostramos aquí es sólo un ejemplo del mensaje que aparecerá en tu línea de comandos. + + + + + +En Windows debes ejecutar el siguiente comando. **(No olvides incluir el punto `.` al final)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> El punto `.` es crucial porque le dice al script que instale Django en el directorio actual (para el cual el punto `.` sirve de abreviatura). +> +> **Nota** Cuando teclees los comandos de arriba, recuerda que sólo tienes que escribir la parte que empieza por `django-admin.exe`. La parte de `(myvenv) C:\Users\Name\djangogirls>` que mostramos aquí es sólo un ejemplo del mensaje que aparecerá en tu línea de comandos. + + + +`django-admin.py` es un script que creará los archivos y directorios para ti. Ahora deberías tener una estructura de directorios parecida a esta: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Nota**: en tu estructura de directorios, también verás el directorio `venv` que creamos anteriormente. + +`manage.py` es un script que ayuda con la administración del sitio. Con él 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. + +Recuerdas cuando hablamos de una cartera que debía comprobar dónde entregar una carta? El archivo `urls.py` contiene una lista de los patrones utilizados por `urlresolver`. + +Por ahora vamos a ignorar el resto de archivos porque no los vamos a cambiar. ¡Sólo acuérdate de no borrarlos accidentalmente! + +## Cambiar 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. + +**Nota**: Ten en cuenta que `settings.py` es un archivo normal, como cualquier otro. Puedes abrirlo con el editor de texto, usando "file -> open" en el menu de acciones. Esto te debería llevar a la típica ventana donde puedes buscar el archivo `settings.py` y seleccionarlo. Como alternativa, puedes abrir el archivo haciendo click derecho en la carpeta djangogirls en tu escritorio. Luego, selecciona tu editor de texto en la lista. Elegir el editor es importante puesto que puede que tengas otros programas que pueden abrir el archivo pero que no te dejaran editarlo. + +Sería bueno tener el horario correcto en nuestro sitio web. Ve a [lista de Wikipedia de las zonas horarias](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) y copia tu zona horaria (TZ) (e.g. `Europa/Berlín`). + +En `settings.py`, encuentra la línea que contiene `TIME_ZONE` y modifícala para elegir tu zona horaria. Por ejemplo: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +Un código de idioma tiene dos partes: el idioma, p.ej. `en` para inglés o `de` para alemán, y el código de país, p.ej. `de` para Alemania o `ch` para Suiza. Si tu idioma nativo no es el inglés, puedes añadir lo siguiente para cambiar el idioma de los botones y notificaciones de Django. Así tendrás el botón "Cancel" traducido al idioma que pongas aquí. [Django viene con muchas traducciones preparadas](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +Si quieres un idioma diferente, cambia el código de idioma cambiando la siguiente línea: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'es-es' +``` + +También tenemos que añadir una ruta para archivos estáticos. (Veremos todo acerca de archivos estáticos y CSS más adelante.) Ve al *final* del archivo, y justo debajo de la entrada `STATIC_URL`, añade una nueva llamada `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +Cuando `DEBUG` es `True` y `ALLOWED_HOST` esta vacío, el host es validado contra `['localhost', '127,0.0.1', '[::1]']`. Una vez despleguemos nuestra aplicación este no sera el mismo que nuestro nombre de host en PythonAnywhere asi que cambiaremos la siguiente opción: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Nota**: si estas usando un Chromebook, añade esta linea al final del archivo settings.py: `MESSAGE_STORAGE = +'django.contrib.messages.storage.session.SessionStorage'` +> +> Añade también `.c9users.io` a `ALLOWED_HOSTS` si estás usando cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Configurar una base de datos + +Hay una gran variedad de opciones de bases de datos para almacenar los datos de tu sitio. Utilizaremos la que viene por defecto, `sqlite3`. + +Esta ya está configurado en esta parte de tu archivo `mysite/settings.py`: + +{% filename %}mysite/settings.py{% endfilename %} + +```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, 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í: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +Y, ¡terminamos! Es hora de iniciar el servidor web y ver si está funcionando nuestro sitio web! + +## Iniciar el servidor + +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`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Si estas usando un Chromebook, utiliza este comando: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![¡La instalación ha funcionado!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> Miramos como funcionan los servidores web en el capítulo **Cómo funciona el internet**. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/es-ES/django_templates/README.md b/es-ES/django_templates/README.md new file mode 100644 index 00000000000..51032f4e55a --- /dev/null +++ b/es-ES/django_templates/README.md @@ -0,0 +1,106 @@ +# Plantillas de Django + +¡Es hora de mostrar algunos datos! Para ello Django incorpora unas etiquetas de plantillas, **template tags**, muy útiles. + +## ¿Qué son las etiquetas de plantilla? + +Verás, en HTML no se puede escribir código en Python porque los navegadores no lo entienden. Sólo saben HTML. Sabemos que HTML es bastante estático, mientras que Python es mucho más dinámico. + +Las **etiquetas de plantilla de Django** nos permiten insertar elementos de Python dentro del HTML, para que puedas construir sitios web dinámicos más rápida y fácilmente. ¡Genial! + +## Mostrar la plantilla lista de posts + +En el capítulo anterior le dimos a nuestra plantilla una lista de entradas en la variable `posts`. Ahora la vamos a mostrar en HTML. + +Para imprimir una variable en una plantilla de Django, utilizamos llaves dobles con el nombre de la variable dentro, algo así: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Prueba esto en la plantilla `blog/templates/blog/post_list.html`. Ábrela en el editor de código, y cambia todo desde el segundo `
` hasta el tercer `
` por `{{ posts }}`. Guarda el archivo y refresca la página para ver los resultados: + +![Figura 13.1](images/step1.png) + +Como puedes ver, lo que hemos conseguido es esto: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ] > +``` + +Significa que Django lo entiende como una lista de objetos. ¿Recuerdas de **Introducción a Python** cómo podemos mostrar listas? Sí, ¡con bucles for! En una plantilla de Django se hacen así: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} {{ post }}{% endfor %} +``` + +Prueba esto en tu plantilla. + +![Figura 13.2](images/step2.png) + +¡Funciona! Pero queremos que se muestren como los post 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í: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Todo lo que pongas entre `{% for %}` y `{% endfor %}` se repetirá para cada objeto de la lista. Refresca la página:{% endraw %} + +![Figura 13.3](images/step3.png) + +¿Has notado que utilizamos una notación diferente esta vez (`{{ post.title }}` o `{{ post.text }}`)? Estamos accediendo a los datos en cada uno de los campos definidos en nuestro modelo `Post`. También el `|linebreaksbr` está pasando el texto de los post 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 web seguirá funcionando en la Internet pública, ¿no? Vamos a intentar desplegar de nuevo en PythonAnywhere. Aquí va un resumen de los pasos… + +* Lo primero, sube tu código a GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Luego, vuelve a entrar en [PythonAnywhere](https://www.pythonanywhere.com/consoles/) y ve a tu **consola Bash** (o inicia una nueva), y ejecuta: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Recuerda sustituir `` con tu subdominio de PythonAnywhere real, sin los paréntesis angulares.) + +* Y finalmente, dirígete a la [página "Web"](https://www.pythonanywhere.com/web_app_setup/) y haz click en **Reload** en tu aplicación web. (Para ir a otras páginas de PythonAnywhere desde la consola, haz click en el botón de la esquina superior derecha.) Los cambios deberían estar visibles en https://subdomain.pythonanywhere.com -- ¡compruébalo en en navegador! Si ves distintas publicaciones en el sitio en PythonAnywhere de las que tienes en tu servidor local, es lo normal. Tienes dos bases de datos, una en tu ordenador local y otra en PythonAnywhere y no tienen por qué tener el mismo contenido. + +¡Felicidades! Ahora intenta añadir un nuevo post en tu administrador de Django (recuerda añadir published_date!) Asegúrate de que estas en el administrador de Django de PytonAnywhere, https://tunombre.pythonanywhere.com/admin. Luego actualiza tu página para ver si los posts aparecen. + +¿Funciona de maravilla? ¡Estamos orgullosas! Aléjate un rato del ordenador, te has ganado un descanso. :) + +![Figura 13.4](images/donut.png) \ No newline at end of file diff --git a/es-ES/django_urls/README.md b/es-ES/django_urls/README.md new file mode 100644 index 00000000000..c2e15fdb712 --- /dev/null +++ b/es-ES/django_urls/README.md @@ -0,0 +1,103 @@ +# URLs en Django + +Estamos a punto de construir nuestra primera página web: ¡una página de inicio para el blog! Pero primero, vamos a aprender un poco acerca de las urls en Django. + +## ¿Qué es una URL? + +Una URL es una dirección de la web. Puedes ver una URL cada vez que visitas una página. Se ve en la barra de direcciones del navegador. (Sí! ¡`127.0.0.1:8000` es una URL! Y `https://djangogirls.org` también es una URL.) + +![URL](images/url.png) + +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 utilizamos algo que se llama `URLconf` (configuración de URL). URLconf es un conjunto de patrones que Django intentará comparar con la URL recibida para encontrar la vista correcta. + +## ¿Cómo funcionan las URLs en Django? + +Vamos a abrir el archivo `mysite/urls.py` en el editor de código de tu elección y veamos lo que tiene: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +Como puedes ver, Django ya puso algo aquí por nosotros. + +Líneas entre triples comillas (`'''` o `"""`) son llamadas docstrings - puedes escribirlos en la parte superior de un archivo, clase o método para describir lo que hace. No serán ejecutadas por Python. + +La URL de admin, que hemos visitado en el capítulo anterior ya está aquí: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +Esta linea dice que para cada URL que empieza con `admin/` Django encontrará su correspondiente *view*. En este caso estamos incluyendo muchas URLs admin así que no todo está empaquetado en este pequeño archivo. Es más limpio y legible. + +## ¡Tu primera URL de Django! + +¡Es hora de crear nuestra primera URL! Queremos que 'http://127.0.0.1:8000/' sea la página de inicio del blog y que muestre una lista de post. + +También queremos mantener limpio el archivo `mysite/urls.py`, así que vamos a importar las urls de nuestra aplicación `blog` en el archivo principal `mysite/urls.py`. + +Vamos, añade la línea para importar `blog.urls`. Tú también necesitarás cambiar la línea `desde django.urls...` porque estaremos usando la función `include` aquí, así que se necesitará añadir ese import a la línea. + +El archivo `mysite/urls.py` debería verse ahora así: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Ahora Django redirigirá todo lo que entre a 'http://127.0.0.1:8000/' hacia `blog.urls` y buscará más instrucciones allí. + +## blog.urls + +Crea un nuevo fichero vacío llamado `urls.py` el el directorio `blog`, y ábrelo en el editor de código. ¡Vale! Añade las dos primeras líneas: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Aquí estamos importando la función de Django `path` y todos nuestras `views` desde la aplicación `blog` (no tenemos una aun, pero veremos eso en un minuto!) + +Luego de esto, podemos agregar nuestro primer patrón URL: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +Como puedes ver, estamos asociando una vista (`view`) llamada `post_list` a la URL raíz. Este patrón de URL coincidirá con una cadena vacía y el solucionador de URL de Django ignorará el nombre de dominio (es decir, http://127.0.0.1:8000/) que prefija la ruta de URL completa. Este patrón le dirá a Django que `views.post_list` es el lugar correcto al que ir si alguien entra a tu sitio web con la dirección 'http://127.0.0.1:8000/'. + +La última parte `name='post_list'` es el nombre de la URL que se utilizará para identificar a la vista. Puede coincidir con el nombre de la vista pero también puede ser algo completamente distinto. Utilizaremos las URL con nombre más delante en el proyecto así que es importante darle un nombre a cada URL de la aplicación. También deberíamos intentar mantener los nombres de las URL únicos y fáciles de recordar. + +Si tratas de visitar http://127.0.0.1:8000/ ahora, encontrarás un mensaje de error 'web page not available' a algo así. Esto es porque el servidor (¿recuerdas que escribimos `runserver`?) ya no está funcionando. Mira la ventana de la consola del servidor para saber por qué. + +![Error](images/error1.png) + +La consola esta mostrando un error, pero no te preocupes - de hecho es muy útil: está diciendote que **no existe el atributo 'post_list'**. Ese es el nombre del *view* que Django está tratando de encontrar y usar, pero aun no lo hemos creado. En esta etapa tu `/admin/` tampoco funcionará. No te preocupes, ya llegaremos a eso. Si ves un error diferente, intenta reiniciar el servidor web. Para hacerlo, en la ventana de la consola que ejecuta el servidor web, deténgalo presionando Ctrl+C (las teclas juntas Control y C). En Windows, es posible que deba presionar Ctrl+Break. Luego, debe reiniciar el servidor web ejecutando un comando `python manage.py runserver`. + +> Si quieres saber más sobre URLconfs de Django, mira la documentación oficial: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/es-ES/django_views/README.md b/es-ES/django_views/README.md new file mode 100644 index 00000000000..505951e21b5 --- /dev/null +++ b/es-ES/django_views/README.md @@ -0,0 +1,44 @@ +# Vistas en Django - ¡Hora de crear! + +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. Pedirá información del `modelo` que has creado antes y se la pasará a la `plantilla`. Crearemos una plantilla en el próximo capítulo. Las vistas son sólo métodos de Python que son un poco más complicados que los que escribimos en el capítulo **Introducción a Python**. + +Las Vistas se colocan en el archivo `views.py`. Agregaremos nuestras *views* al archivo `blog/views.py`. + +## blog/views.py + +Vale, abre éste fichero en el editor y mira lo que hay en él: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +No hay demasiadas cosas aquí todavía. + +Recuerda que las lineas que comienzan con `#` son comentarios - significa que Python no las ejecutará. + +Creemos una *vista (view)* como sugiere el comentario. Añade la siguiente mini-vista por debajo: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Como puedes ver, hemos creado una función (`def`) llamada `post_list` que acepta `request` y `return` una función `render` que reproduce (construye) nuestra plantilla `blog/post_list.html`. + +Guarda el archivo, ve a http://127.0.0.1:8000/ y mira lo que hemos hecho. + +¡Otro error! Leamos lo que está pasando ahora: + +![Error](images/error.png) + +Esto demuestra que el servidor está funcionando otra vez, al menos, pero todavía no se ve bien, ¿No? No te preocupes, es sólo una página de error, ¡nada a que temer! Al igual que los mensajes de error en la consola, estos son realmente muy útiles. Puedes leer que la *TemplateDoesNotExist*. Vamos a corregir este error y crear una plantilla en el próximo capítulo! + +> Obtenga más información sobre las vistas de Django leyendo la documentación oficial: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/es-ES/dynamic_data_in_templates/README.md b/es-ES/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..cf1a91c6c84 --- /dev/null +++ b/es-ES/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Datos dinámicos en 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 haremos realmente para que nuestros posts aparezcan en nuestra plantilla HTML? Porque eso es lo que queremos, tomar algún contenido (modelos guardados en la base de datos) y mostrarlo adecuadamente en nuestra plantilla, ¿no? + +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. En una *vista* decidimos que (modelo) se mostrará en una plantilla. + +Muy bien, entonces ¿cómo lo logramos? + +Tenemos que abrir `blog/views.py` en el editor. De momento `post_list` *view* tiene esto: + +{% filename %}blog/views.py{% endfilename %} + +```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 línea `from .models import Post` de la siguiente forma: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +El punto antes de `models` indica el *directorio actual* o la *aplicación actual*. Ambos, `views.py` y `models.py` están en el mismo directorio. Esto significa que podemos utilizar `.` y el nombre del archivo (sin `.py`). Ahora importamos el nombre del modelo (`Post`). + +¿Pero ahora qué sigue? Para tomar posts reales del modelo `Post`, necesitamos algo llamado `QuerySet`. + +## QuerySet + +Ya debes estar familiarizada con la forma en que funcionan los QuerySets. Hablamos de ellos en el capítulo [Django ORM (QuerySets)](../django_orm/README.md). + +Así que ahora nos interesa tener una lista de post publicados ordenados por `published_date` (fecha de publicación), ¿no? ¡Ya lo hicimos en el capítulo QuerySets! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Abre `blog/views.py` en el editor, y añade este trozo de código a la función `def post_list(request)` -- pero no te olvides de añadir `from django.utils import timezone` antes: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +Para mostrar nuestro QuerySet en nuestra lista de posts, nos quedan dos cosas que hacer: + +1. Pasar el QuerySet de `posts` al contexto de la plantilla, cambiando la llamada a la función `render`. +2. Modificar la plantilla para mostrar el QuerySet de `posts`. Llegaremos a eso más adelante en un próximo capítulo. + +Fíjate en que creamos una *variable* para el QuerySet: `posts`. Trátala como si fuera el nombre de nuestro QuerySet. De aquí en adelante vamos a referirnos al QuerySet con ese nombre. + +En la función `render` tenemos el parámetro `request` (todo lo que recibimos del usuario via Internet) y otro parámetro dándole el archivo de la plantilla (`'blog/post_list.html'`). El último parámetro, que se ve así: `{}` es un lugar 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}`. Fíjate en que la parte antes de `:` es una cadena; tienes que envolverla con comillas: `"`. + +Finalmente nuestro archivo `blog/views.py` debería verse así: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +¡Terminamos! Ahora regresemos a nuestra plantilla y mostremos este QuerySet. + +¿Quieres leer un poco más sobre QuerySets en Django? Debería mirar aquí: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/es-ES/extend_your_application/README.md b/es-ES/extend_your_application/README.md new file mode 100644 index 00000000000..5143617e802 --- /dev/null +++ b/es-ES/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extiende tu aplicación + +Ya hemos completado todos los diferentes pasos necesarios para la creación de nuestro sitio web: sabemos cómo escribir un modelo, URL, vista y plantilla. También sabemos cómo hacer que nuestro sitio web sea bonito. + +¡Hora de practicar! + +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 a la página de detalle de una publicación + +Empezaremos añadiendo un enlace al fichero `blog/templates/blog/post_list.html`. Ábrelo en el editor; de momento debería tener este contenido: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}Queremos tener un link del titulo de una publicación en la lista de publicaciones al detalle de la misma. Cambiemos `

{{ post.title }}

` para enlazarla a la página detalle del post:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Es hora de explicar el misterioso`{% url 'post_detail' pk=post.pk %}`. Como probablemente sospeches, la notación `{% %}` significa que estamos utilizando Django template tags. ¡Esta vez usaremos uno que creará un URL para nosotros!{% endraw %} + +La parte de`post_detail` significa que Django estará esperando un URL en `blog/urls.py` con el nombre=post_detail + +¿Y ahora qué pasa con `pk=post.pk`? `pk` abrevia clave primaria (primary key), la cual es un identificador único para cada registro en una base de datos. Cada modelo de Django tiene un campo que sirve como clave primaria, y cualquier otro nombre que tiene, también se puede llamar "pk". Porque no especificamos una clave primaria en nuestro modelo `Post`, Django creará una por nosotros (por defecto, un campo llamado "id" con un número que se incrementará por cada registro, por ejemplo 1, 2, 3) y lo agregará como un campo en cada uno de nuestros posts. Accedemos a la clave primaria escribiendo `post.pk`, del mismo modo en que accedemos a otros campos (`title`, `author`, etc.) en nuestro objeto `Post`! + +Ahora cuando vayamos a: http://127.0.0.1:8000/ tendremos un error (como era de esperar, ya que no tenemos una URL o una *vista* para `post_detail`). Se verá así: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Crea una URL al detalle de una publicación + +Vamos a crear una URL en `urls.py` para nuestra *view* `post_detail`! + +Queremos que el detalle de la primera entrada se visualice en esta **URL**: http://127.0.0.1:8000/post/1/ + +Vamos a crear una URL en el fichero `blog/urls.py` que dirija a Django hacia una *vista* llamada `post_detail`, que mostrará una entrada de blog completa. Abre el fichero `blog/urls.py` en el editor, y añade la línea `path('post//', views.post_detail, name='post_detail'),` para que el fichero quede así: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +Esta parte `post//` especifica un patrón de URL – ahora lo explicamos: + +- `post/` significa que la URL debería empezar con la palabra **post** seguida por una **/**. Hasta aquí bien. +- `` – esta parte tiene más miga. Significa que Django buscará un número entero y se lo pasará a la vista en una variable llamada `pk`. +- `/` – necesitamos otra **/** al final de la URL. + +Esto quiere decir que si pones `http://127.0.0.1:8000/post/5/` en tu navegador, Django entenderá que estás buscando una *vista* llamada `post_detail` y transferirá la información de que `pk` es igual a `5` a esa *vista*. + +OK, hemos añadido un nuevo patrón de URL a `blog/urls.py`! Actualizamos la pagina: http://127.0.0.1:8000/ y boom! El servidor vuelve a dejar de funcionar. Echa un vistazo a la consola – como era de esperar, hay otro error! + +![AttributeError](images/attribute_error2.png) + +¿Recuerdas cual es el próximo paso? ¡Añadir una vista! + +## Añade la vista de detalle de la publicación + +Esta vez nuestra *vista* tomará un parámetro adicional `pk`. Nuestra *vista* necesita recibirlo, ¿verdad? Así que definiremos nuestra función como `def post_detail (request, pk):`. Tenga en cuenta que este parametro debe tener exactamente el mismo nombre que el que especificamos en `urls` (`pk`). ¡También tenga en cuenta que omitir esta variable es incorrecto y resultará en un error! + +Ahora, queremos obtener solo un post. Para ello podemos usar querysets como este: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +Pero este código tiene un problema. Si no hay ningún `Post` con esa `clave primaria` (`pk`), ¡tendremos un error muy feo! + +![DoesNotExist error](images/does_not_exist2.png) + +¡No queremos eso! Por suerte, Django tiene una función que se encarga de eso: `get_object_or_404`. En caso de que no haya ningún `Post` con el `pk` dado se mostrará una página mucho más agradable, `Page Not Found 404`. + +![Page not found](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 tan importante, así que lo omitiremos. + +¡Es hora de agregar una *view* a nuestro archivo `views.py`! + +En `blog/urls.py` creamos un regla de URL denominada `post_detail` que hace referencia a una vista llamada `view.post_detail`. Esto significa que Django va a estar esperando una función llamada `post_detail` de vista en `blog/views.py`. + +Deberíamos abrir `blog/views.py` en el editor y añadir el siguiente código cerca de los otros import `from`: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +Y al final del archivo agregamos nuestra *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): +    post = get_object_or_404(Post, pk=pk) +    return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Sí. Es hora de actualizar la página: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +¡Funcionó! Pero ¿qué pasa cuando haces click en un enlace en el título del post? + +![TemplateDoesNotExist error](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! + +## Crear una plantilla para post detail + +Vamos crear un fichero en `blog/templates/blog` llamado `post_detail.html`, y abrirlo en el editor de código. + +Introduzca el siguiente código: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if 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? + +{% raw %}`{% if ... %} ... {% endif %}` es un template tag que podemos usar cuando querramos ver algo. (Recuerdas `if ... else ..` del capítulo **Intruducción a Python**?) Ahora queremos mirar si la `published_date` de un post no esta vacía.{% endraw %} + +Bien, podemos actualizar nuestra página y ver si `TemplateDoesNotExist` se ha ido. + +![Post detail page](images/post_detail2.png) + +¡Yay! ¡Funciona! + +# Hora de despliegue! + +Sería bueno verificar que tu sitio web aún funcionará en PythonAnywhere, ¿cierto? Intentemos desplegar de nuevo. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push + + +Luego, en una [consola Bash de PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Recuerda sustituir `` con tu subdominio de PythonAnywhere real, sin los paréntesis angulares.) + +## Actualizar los ficheros estáticos (static files) en el servidor + +Normalmente, los servidores como PythonAnywhere tratan los ficheros estáticos (como los ficheros CSS) de manera diferente a los ficheros de Python. Se llaman estáticos porque el servidor no debe ejecutarlos, sino servirlos tal cual. Y por ello se tratan por separado para servirlos más rápido. Como consecuencia, si cambiamos nuestros ficheros CSS, tenemos que ejecutar un comando extra en el servidor para decirle que los actualice. Este comando se llama `collectstatic`. + +Activa el virtualenv si no estaba activado de antes (en PythonAnywhere se usa el comando `workon`, es igual que el comando `source myenv/bin/activate` que usamos en local): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +El comando `manage.py collectstatic` es un poco como el comando `manage.py migrate`. Hacemos cambios en nuestro código y luego le decimos a Django que los *aplique*, bien a la colección de ficheros estáticos o bien a la base de datos. + +En cualquier caso, ahora estaremos listos para saltar sobre la [página "Web"](https://www.pythonanywhere.com/web_app_setup/) (desde el botón del menú en el lado superior derecho de la consola), realizar la **Recarga**, y mirar en la página https://subdomain.pythonanywhere.com para ver el resultado. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/es-ES/how_the_internet_works/README.md b/es-ES/how_the_internet_works/README.md new file mode 100644 index 00000000000..b773953ae67 --- /dev/null +++ b/es-ES/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# ¿Cómo funciona Internet? + +> Para lectores en casa: este capítulo está cubierto en el video [¿Cómo funciona Internet?](https://www.youtube.com/watch?v=oM9yAA09wdc). +> +> Este capitulo está inspirado en la charla "How the Internet works" de Jessica McKellar (http://web.mit.edu/jesstess/www/). + +Apostamos a que utilizas Internet todos los días. Pero, ¿sabes lo que pasa cuando escribes una dirección como http://djangogirls.org en tu navegador y presionas `enter`? + +La primera cosa que necesitas entender, es que una página web consiste de un puñado de archivos guardados en el disco duro -- como tus películas, música, o imágenes. Sin embargo, hay una parte que es única para los sitios web: ellos incluyen código computarizado llamado HTML. + +Si tu no estás familiarizado con la programación, puede ser difícil de comprender HTML a la primera, pero tus navegadores web (como Chrome, Safari, Firefox, etc.) lo aman. Los navegadores están diseñados para entender este código, seguir sus instrucciones y presentar estos archivos de los cuales está hecho tu sitio web, exactamente de la forma que quieres. + +Como cualquier otro archivo, tenemos que guardar los archivos HTML en algún lugar de un disco duro. Para Internet, utilizamos equipos especiales, de gran alcance llamados *servidores*. Estos 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 *sirven* los datos. + +OK, pero quieres saber cómo Internet se ve, ¿cierto? + +¡Te hemos hecho una imagen! Luce algo así: + +![Figura 1.1](images/internet_1.png) + +Parece un lío, ¿no? De hecho, es una red de máquinas interconectadas (los *servidores* que nombramos anteriormente). ¡Cientos de miles de máquinas! ¡Muchos, muchos kilómetros de cables alrededor del mundo! Puedes visitar el sitio web Submarine Cable Map (http://submarinecablemap.com/) y ver lo complicada que es la red. Aquí hay una captura de pantalla de la página web: + +![Figura 1.2](images/internet_3.png) + +Es fascinante, ¿no? Pero sería imposible tener un cable entre todas y cada una de las máquinas conectadas a internet. Así que, para llegar a una máquina (por ejemplo la que aloja http://djangogirls.org) tenemos que elevar una solicitud mediante una gran cantidad de máquinas diferentes. + +Se parece a esto: + +![Figura 1.3](images/internet_2.png) + +Imagina que cuando escribes http://djangogirls.org, estas enviando una carta que dice: "Estimadas Django Girls, me gustaría ver su sitio web djangogirls.org. Por favor, envíenmelo!" + +Tu carta va hacia la oficina de correo más cercana. Luego va a otra que es un poco más cerca de su destinatario, luego otra y otra hasta que es entregada a su destino. La única cosa diferente es que si envías muchas cartas (*paquetes de datos*) al mismo lugar, cada una podría ir a través de oficinas de correos totalmente distintas (*routers*). Esto depende de cómo se distribuyen en cada oficina. + +![Figura 1.4](images/internet_4.png) + +Así es como funciona - se envían mensajes y se espera una respuesta. En lugar de papel y lápiz, se usan 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 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 en cierta manera como los viejos directorios telefónicos donde puedes buscar el nombre de la persona que se deseas contactar y encontrar 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 se aplica a los *paquetes de datos* que envía para ver un sitio Web. Utilizamos un protocolo llamado HTTP (Protocolo de transferencia de hipertexto). + +Así que, básicamente, cuando tienes un sitio web necesitas tener un *servidor* (la máquina) donde este vive. Cuando el *servidor* recibe una *petición* entrante (en una carta), este envía su sitio de Internet (en otra carta). + +Ya que este es un tutorial de Django, puede que te preguntes que lo que Django hace. 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. :) + +Suficiente conversación - tiempo de crear! \ No newline at end of file diff --git a/es-ES/html/README.md b/es-ES/html/README.md new file mode 100644 index 00000000000..03e17644fec --- /dev/null +++ b/es-ES/html/README.md @@ -0,0 +1,227 @@ +# Introducción a HTML + +Te estarás preguntando, ¿qué es una plantilla? + +Una plantilla es un archivo que podemos reutilizar para presentar información diferente de forma consistente - por ejemplo, podrías 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 (el HTML que mencionamos en el primer capítulo **Cómo funciona Internet**). + +## ¿Qué es HTML? + +HTML es un código simple que es interpretado por tu navegador web - como Chrome, Firefox o Safari - para mostrar una página web al usuario. + +HTML significa HyperText Markup Language - en español, Lenguaje de Marcas de HyperTexto. **HyperText** -hipertexto en español- 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 representan **elementos** de marcado. + +## ¡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 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 estés preguntando por qué necesitamos dos directorios llamados `blog` – como verás más adelante, es una convención de nombres que nos facilitará la vida cuando las cosas se pongan más complicadas.) + +Y ahora crea un archivo `post_list.html` (déjalo en blanco por ahora) dentro de la carpeta `blog/templates/blog`. + +Mira cómo se ve su sitio web ahora: http://127.0.0.1:8000/ + +> Si todavía tienes un error `TemplateDoesNotExist`, intenta reiniciar tu servidor. Ve a la consola, para el servidor pulsando Ctrl+C (las teclas Control y C a la vez) y reinicialo ejecuntado el comando `python manage.py runserver`. + +![Figura 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Abre un fichero nuevo en el editor y escribe lo siguiente: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +Ahora, cómo luce tu sitio web? Haz click para ver: http://127.0.0.1:8000/ + +![Figura 11.2](images/step3.png) + +It worked. Nice work there! :) + +* The line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 + +## Cabeza y 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 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. + +Por ejemplo, puedes ponerle un título a la página web dentro de la ``, así: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Guarda el archivo y actualiza tu página. + +![Figura 11.3](images/step4.png) + +¿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 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 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 *anidación* de elementos - si no lo haces, el navegador puede no ser capaz de interpretarlos apropiadamente y tu página se mostrará incorrectamente. + +## Personaliza tu plantilla + +¡Ahora puedes divertirte un poco y tratar de personalizar tu plantilla! Aquí hay algunas etiquetas útiles para eso: + +* `

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 `
` +* `

Un párrafo de texto

` +* `texto` - pone en cursiva tu texto +* `texto` - pone en negrita tu texto +* `
` va en otra línea (no puedes poner nada dentro de br y no hay etiqueta de cierre) +* `link` - crea un vínculo +* `
  • primer elemento
  • segundo elemento
` - crea una lista, ¡igual que esta! +* `
` - define una sección de la página +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Aca va un ejemplo de una plantilla completa, copialo y pegalo en `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +Nos da este efecto: + +![Figura 11.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**. + +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. + +## Una cosa más: ¡despliega! + +Sería bueno ver todo esto disponible en Internet, ¿no? Hagamos otro despliegue en PythonAnywhere: + +### Haz commit, y sube tu código a GitHub + +En primer lugar, vamos a ver qué archivos han cambiado desde la última puesta en marcha (ejecute estos comandos localmente, no en PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Asegúrate de que estás en el directorio `djangogirls` y vamos a decirle a `git` que incluya todos los cambios en este directorio: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% filename %}command-line{% endfilename %} + + $ git status + + +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. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "Cambie el HTML para la página." + + +> **Note** Make sure you use double quotes around the commit message. + +Una vez hecho esto, subimos (push) los cambios a Github: + +{% filename %}command-line{% endfilename %} + + $ git push + + +### Descarga tu nuevo código a PythonAnywhere y actualiza tu aplicación web + +* Abre la [página de consolas de PythonAnywhere](https://www.pythonanywhere.com/consoles/) y ve a tu **consola Bash** (o comienza una nueva). Luego, ejecuta: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +Tú necesitarás sustituir `` con tu actual nombre de subdominio PythonAnywhere, sin los paréntesis angulares o corchetes. Tu nombre de subdominio es normalmente tu nombre de usuario PythonAnywhere, pero en algunos casos ésto puede ser un poco diferente (tal como si tu nombre de usuario contiene letras mayúsculas). Así si éste comando no funciona, usa el comando `ls`(listar archivos) para encontrar tu actual subdominio/nombre-carpeta, y muévete allí con `cd `. + +Ahora mira cómo se descarga tu código. Si quieres comprobar que efectivamente ha llegado bien, puedes ir a la **página "Files"** y ver tu código en PythonAnywhere (puedes ir a otras páginas de PythonAnywhere desde el botón de la esquina superior derecha de la página de la consola). + +* Finalmente, ve a la [página "Web"](https://www.pythonanywhere.com/web_app_setup/) y pulsa **Reload** en tu aplicación web. + +¡Tu nueva versión ya debería estar publicada! Ve al navegador y refresca tu sitio web. Deberías ver los cambios. :) \ No newline at end of file diff --git a/es-ES/install_git.md b/es-ES/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/es-ES/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/es-ES/installation/README.md b/es-ES/installation/README.md new file mode 100644 index 00000000000..17bf41cfe56 --- /dev/null +++ b/es-ES/installation/README.md @@ -0,0 +1,68 @@ +# Si estás haciendo el tutorial en casa + +Si estás haciendo el tutorial en casa, y no en uno de los [eventos de Django Girls](https://djangogirls.org/events/), puedes saltar este capítulo por completo e ir directamente al capítulo [¿cómo funciona Internet?](../how_the_internet_works/README.md). + +Esto es porque cubrimos las instalaciones de cosas a medida que se requieran en el tutorial -- esta es solamente una página adicional que reúne toda la información de instalación en un solo lugar (Lo que es útil para algunos formatos de taller). Puedes escoger instalar todo lo que está en esta página ya mismo si lo deseas. Pero si tu quieres empezar a aprender cosas antes de instalar un grupo de materiales en tu computadora, salta éste capítulo y nosotros te explicaremos las partes de la instalación luego, como éstos sean necesarios. + +¡Buena suerte! + +# Si tu estás asistiendo a un workshop + +Si tu estás asistiendo a uno de los [Django Girls events](https://djangogirls.org/events/): + +* Tu workshop puede tener una "fiesta de instalación" antes del workshop principal. Si tu estás en un equipo de instalación, ¡ésta página es para ti! Sigue las instrucciones aquí para obtener todo lo que tu necesitas para el workshop de instalación, con la ayuda de los entrenadores si lo necesitas. Entonces en el workshop principal, tu estarás preparado para saltar las instrucciones de instalación que encontrarás en el tutorial principal cuando llegues a ellos. +* Los organizadores de tu taller pueden preguntarte que en casa intentes instalar todo en tu computadora antes de iniciar el taller. Si tu has estado preguntando para hacer esto, ¡ésta página es para ti! Sigue las instrucciones aquí, como mejor puedas. Entonces en el taller principal, cuando estés en uno de los pasos de la instalación del tutorial; y si tu no tenías esa pieza instalada, puedes pedir ayuda a uno de tus entrenadores. +* Si tu taller no tiene una estación de instalación ( o tu no podías asistir), y si los organizadores no te preguntan para que intentes instalar todo antes de tu llegada, salta ésta página y ve al capítulo [Cómo el internet funciona](../how_the_internet_works/README.md). Tú estarás instalando todo lo que necesitas para trabajar a través de el tutorial. + +# Instalación + +En este tutorial vas a construir un blog. Según, cómo vayas a través de el tutorial tu serás instruido en cómo instalar varios softwares en tu computadora y configurar algunas cuentas online como sean necesarias. Ésta página reune todas las instalaciones e instrucciones del registro en un lugar ( el cual es útil para algunos formatos del taller). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Breve introducción a la línea de comandos {#command-line} + +Muchos de los pasos citados abajo hacen referencia a la "consola", "terminal", "ventana de comandos", o "línea de comandos" -- todos éstos términos significan la misma cosa: una ventana en tu computadora donde tu puedes entrar comandos. Cuando tu estás en el tutorial principal, tu aprenderás más acerca de la línea de comandos. Por ahora, la parte principal que tu necesitas es saber cómo abrir una ventana de comandos y cómo luce: {% include "/intro_to_command_line/open_instructions.md" %} + +# Instalar Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Instala un Editor de Código {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Crea un entorno virtual (virtualenv) e instala Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Instalar Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Ve a [GitHub.com](https://www.github.com) y registrate para una nueva y gratuita cuenta de usuario. Asegúrate de recordar tu contraseña ( añadela a tu manejador de contraseñas, si tu usas uno). + +# Create a PythonAnywhere account {#pythonanywhere-account} + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Comienza a leer + +Felicitaciones, ¡tú tienes todo configurado y listo para avanzar! si tú aún tienes algún tiempo antes de el taller, sería útil empezar a leer un poco de los capítulos iniciales: + +* [¿Cómo funciona internet?](../how_the_internet_works/README.md) + +* [Introducción a la línea de comandos](../intro_to_command_line/README.md) + +* [Introducción a Python](../python_introduction/README.md) + +* [¿Qué es Django?](../django/README.md) + +# ¡Disfrutar el taller! + +Cuando tú comiences el taller, estarás habilitada para ir directamente a [¡Tu primer proyecto en Django!](../django_start_project/README.md) porque tú ya cubriste el material en los capítulos anteriores. \ No newline at end of file diff --git a/es-ES/instructions.md b/es-ES/instructions.md new file mode 100644 index 00000000000..30bd493b11b --- /dev/null +++ b/es-ES/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command dnf is not found. In that case you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/es-ES/intro_to_command_line/README.md b/es-ES/intro_to_command_line/README.md new file mode 100644 index 00000000000..a2c5a581396 --- /dev/null +++ b/es-ES/intro_to_command_line/README.md @@ -0,0 +1,436 @@ +# Introducción a la interfaz de línea de comandos + +> Para los lectores en casa: este capítulo puede verse en el vídeo [Tu nuevo amigo: Línea de Comandos](https://www.youtube.com/watch?v=jvZLWhkzX-8). + +Es emocionante, ¿verdad? ¡Vas a escribir tu primera línea de código en pocos minutos! :) + +**Permítenos presentarte a tu primer amigo nuevo: ¡la línea de comandos!** + +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. + +> **Nota** Ten en cuenta que a lo largo de este libro usamos los términos 'directorio' y 'carpeta' indistintamente pero son la misma cosa. + +## ¿Qué es la línea de comandos? + +La ventana, que generalmente es llamada **línea de comandos** ó **interfaz de línea de comandos**, es una aplicación basada en texto para ver, manejar y manipular archivos en tu ordenador. Similar a Windows Explorer o Finder en Mac, pero sin la interfaz gráfica. Otros nombres para la línea de comandos son: *cmd*, *CLI*, *prompt* -símbolo de sistema-, *console* -consola- o *terminal*. + +## Abrir la interfaz de línea de comandos + +Para empezar con algunos experimentos necesitarás abrir nuestra interfaz de línea de comandos en primer lugar. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## Símbolo del Sistema (Prompt) + +Ahora deberías ver una pantalla blanca o negra que espera a que introduzcas tus comandos. + + + +Si estás en Mac o Linux, probablemente veas una `$`, como ésta: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +En Windows, probablemente veas un `>`, como éste: + +{% filename %}command-line{% endfilename %} + + > + + +Echa un vistazo a la sección anterior sobre Linux -- podrás consultar más cuando llegues a PythonAnywhere más adelante en este tutorial. + + + +Cada comando vendrá precedido por un `$` o un `>` y un espacio, pero no debes escribirlos tú mismo. El ordenador lo hará por ti. :) + +> Solo una pequeña anotación: en tu caso puede que haya algo como `C:\Users\ola>` o `Olas-MacBook-Air:~ ola$` antes del símbolo de introducción, lo cual es 100% NORMAL. + +La parte superior incluye el `$` o el `>` que es llamado en la *línea de comandos*, o mas corto *prompt*. Introduce algo allí. + +En el tutorial, cuando queramos introducir un comando, incluye el `$` o `>`, y ocasionalmente más a la izquierda. Ignora la parte izquierda solamente escribiendo el comando, el cuál inicia después de el prompt. + +## Tu primer comando (¡BIEN!) + +Iniciemos por teclear este comando: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +Y luego presiona `enter`. Esto será nuestro resultado: + +{% filename %}command-line{% endfilename %} + + $ whoami olasitarska + + +Como puedes ver, el computador ha solo impreso tu nombre de usuario. Ordenado, ¿ah? :) + +> Intenta escribir cada comando; no copies y pegues. ¡De ésta manera lo recordarás! + +## Fundamentos + +Cada sistema operativo tiene un poco diferente la configuración de los comandos para la consola, así que asegurate de seguir las instrucciones para tu sistema operativo. Intentemos esto, ¿Verdad? + +### Directorio actual + +Sería bueno saber dónde estamos ahora, ¿Correcto? Veamos. Escribe éste comando y presiona `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Nota: 'pwd' es para imprimir el directorio de trabajo (print working directory). + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +Probablemente veremos algo similar en tu computador. Una vez que abres la consola o la línea de comandos, usualmente inicias en tu directorio principal. + +* * * + +### Aprende más sobre un comando + +¡Muchos comandos pueden escribirse en el prompt que tiene construído una ayuda que puedes leer! Por ejemplo, aprende más acerca de el comando del directorio actual: + + + +OS X y Linux tienen un comando `man`, el cuál te da una ayuda en comandos. Intenta `man pwd` y ve que dice, o coloca `man` antes de otro comando para ver su ayuda. La salida de `man` nomalmentes es paginada. Usa la barra de espacio para moverte a la siguiente página, y `q` para sallir de la ayuda. + + + + + +Añade un sufijo `/?` para mas comandos que se imprimirán en la página de ayuda. Tú puedes hacer scroll a la ventana de comandos para verlos todos. Intenta `cd /?`. + + + +### Listar ficheros y directorios + +Así que, ¿en qué estamos? Estaría bien saberlo. Veamos: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Cambiar el directorio actual + +Ahora, vamos a nuestro directorio de escritorio: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Escritorio + + +Nota que el nombre del directorio "Escritorio" puede ser traducido al lenguaje de tu cuenta de Linux. Si ese es el caso, tu necesitarás reemplazar `Escritorio` con la traducción del nombre; por ejemplo, `Schreibtisch` para el alemán. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Escritorio + + + + +Verifica si está cambiado actualmente: + + + +{% filename %}command-line{% endfilename %} + + $ pwd /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd C:\Users\olasitarska\Desktop + + + + +¡Aquí está! + +> PRO tip: si tu escribes `cd D` y luego presionas `tab` en tu teclado, la línea de comandos automáticamente llenará el resto de el nombre por el que puedes navegar. Si hay mas que una carpeta iniciando con "D", presiona la tecla `tab` dos veces para obtener una lista de opciones. + +* * * + +### Crear un directorio + +¿Cómo crear un práctico directorio para tu escritorio? Tú puedes hacerlo de esta manera: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% filename %}command-line{% endfilename %} + + > mkdir practice + + + + +Éste pequeño comando creará una carpeta con el nombre `práctica` en tu computador. ¡Tú puedes verificar si está allí en tu Escritorio o ejecutando uno de los siguientes comandos `ls` o `dir`! Intentalo. :) + +> PRO tip: Si tu no quieres escribir el mismo comando una y otra vez, intenta presionando la `flecha arriba` y `flecha abajo` en tu teclado para regresar a través de los comandos recientemente usados. + +* * * + +### ¡Ejercicio! + +Un pequeño reto para ti: en tu nuevo directorio creado `práctica`, crea un directorio llamado `prueba`. (Usa los comandos `cd` y `mkdir`.) + +#### Solución: + + + +{% filename %}command-line{% endfilename %} + + $ cd practica + $ mkdir prueba + $ ls + prueba + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +¡Felicidades! :) + +* * * + +### Limpieza + +No queremos dejar un enredo, así que removamos todo lo que hicimos hasta este momento. + +Primero, necesitamos regresar al Escritorio: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% filename %}command-line{% endfilename %} + + > cd .. + + + + +Usando los `..` con el comando `cd` cambiaremos tu actual directorio al directorio padre( que es, el directorio que contiene tu directorio actual). + +Verifica dónde estás: + + + +{% filename %}command-line{% endfilename %} + + $ pwd /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd C:\Users\olasitarska\Desktop + + + + +Es hora de eliminar el directorio `practica`: + +> **Atención**: Si eliminas los archivos usando `del`, `rmdir` o `rm` no se podrán recuperar, esto significa ¡*el borrado de los archivos será para siempre*! Sé muy cuidados@ coon este comando. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practica + practica, ¿Estás segur@? Y + + + + +¡Hecho! Estás seguro que lo eliminaste realmente, verifica: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### Salir + +¡Eso es todo por ahora! Tú puedes ahora cerrar la línea de comandos o consola sin problemas. Hazlo como un hacker, ¿vale? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Genial, ¿no? :) + +## Resumen + +Aquí está un resumen 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** | +| cd | pwd | Mostrar el directorio actual | **cd** (Windows) o **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (o del) | rm | Eliminar un archivo | **del c:\test\test.txt** | +| rmdir /S | rm -r | Eliminar un Directorio | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | Obtener ayuda para un comando | **cd /?** (Windows) o **man cd** (Mac OS / Linux) | + +Estos son solo algunos de los comandos que tu puedes ejecutar en tu línea de comando o consola, pero no usarás ninguno más por hoy. + +Si eres curios@, [ss64.com](http://ss64.com) contiene una referencia completa de comandos para todos los sistemas operativos. + +## ¿Listo? + +¡Vamos a bucear en Python! \ No newline at end of file diff --git a/es-ES/intro_to_command_line/open_instructions.md b/es-ES/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..08dd61eb1f1 --- /dev/null +++ b/es-ES/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Dependiendo de tu versión de Windows y tu teclado, una de las opciones siguientes debería abrir una ventana de comandos (puede que necesites experimentar un poco, pero no se necesita probar todas estas sugerencias): + +- Ve al menú o pantalla de Inicio, y escribe "Símbolo del Sistema" en el cuadro de búsqueda. +- Ve a Menú de inicio → Windows System → Command Prompt. +- Ve al menú de Inicio → Todos los Programas → Accessorios → Símbolo del Sistema. +- Ve a la pantalla de Inicio, pasa el ratón sobre la esquina inferior izquierda de la pantalla, y haz click en la flecha hacia abajo (en una pantalla táctil, desliza hacia arriba desde la parte baja de la pantalla). La página de la Aplicación debería abrirse. Haz click en Símbolo del Sistema en la sección Sistema de Windows. +- Mantén la tecla especial de Windows de tu teclado y pulsa "X". Elige "Símbolo del Sistema" del menú emergente. +- Mantén pulsada la tecla de Windows y pulsa "R" para abrir una ventana "Ejecutar". Escribe "cmd" en la caja, y haz click en OK. + +![Escribe "cmd" en la ventana "Ejecutar"](../python_installation/images/windows-plus-r.png) + +Más adelante en este tutorial, necesitarás tener dos consolas de comandos abiertas a la misma vez. Sin embargo, en algunas versiones de Windows, si ya tienes abierta una ventana de comandos e intentas abrir otra usando el mismo método, simplemente maximizará la que ya tienes abierta. ¡Inténtalo ahora en tu ordenador y mira qué ocurre! Si solo se abre una ventana de comandos, intenta alguno de los otros métodos explicados anteriormente. Al menos uno de ellos debería abrir una nueva ventana de comandos. + + + + + +Ve a Aplicaciones → Utilidades → Terminal. + + + + + +Probablemente se encuentre en Aplicaciones → Accesorios → Terminal, o Aplicaciones → Sistema → Terminal, aunque esto dependerá de tu sistema. Si no lo encuentras allí, intenta buscarlo en Google. :) + + \ No newline at end of file diff --git a/es-ES/python_installation/README.md b/es-ES/python_installation/README.md new file mode 100644 index 00000000000..111a1a6a69e --- /dev/null +++ b/es-ES/python_installation/README.md @@ -0,0 +1,15 @@ +# Vamos a empezar con Python + +¡Por fin estamos aquí! + +Pero primero, déjanos decirte qué es Python. Python es un lenguaje de programación muy popular que puede ser usado para crear sitios web, juegos, software científico, gráficos, y más, mucho más. + +Python se originó en la década de 1980 y su principal objetivo es ser legible por los seres humanos (¡no sólo por máquinas!). Por esta razón parece mucho más sencillo que otros lenguajes de programación, pero no te preocupes – ¡Python también es realmente poderoso! + +# Instalación de Python + +> **Nota** Si usas un Chromebook, omite este capítulo y asegúrate de seguir las instrucciones de [Chromebook Setup](../chromebook_setup/README.md). +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/es-ES/python_installation/instructions.md b/es-ES/python_installation/instructions.md new file mode 100644 index 00000000000..bfc1e604613 --- /dev/null +++ b/es-ES/python_installation/instructions.md @@ -0,0 +1,117 @@ +> Para lectores en casa: este capitulo se cubre en el vídeo [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA). +> +> Esta sección está basada en un tutorial de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django está escrito en Python. Necesitamos Python para hacer cualquier cosa en Django. ¡Empecemos con instalarlo! Queremos que instales la última versión de Python 3, así que si tienes una versión anterior, necesitarás actualizarla. Si ya tienes la version {{ book.py_min_version }} o una más actualizada no tendrás ningún inconveniente. + +Por favor, instala Python normalmente de la siguiente forma, incluso si tienes Anaconda instalada en el ordenador. + + + +Primero comprueba si tu ordenador ejecuta la versión 32 bits de Windows o la de 64, en "Tipo de sistema" en la página de "Acerca de". Para llegar a esta página, intenta uno de estos métodos: + +* Presiona la tecla de Windows y la tecla Pause/Break al mismo tiempo +* Abre el Panel de Control desde el menú de Windows, después accede a Sistema & y Seguridad, luego a Sistema +* Presiona el botón de Windows, luego accede a Configuración > Sistema > Acerca de +* Busca "Información del sistema" en el menú de Inicio de Windows. Para hacerlo, haz click en el botón de Inicio o pulsa la tecla Windows, entonces empieza a teclear `Información del sistema`. Empezará a proporcionar sugerencias tan pronto como empieces a teclear. Puedes selecionar la entrada una vez se muestre. + +Puedes descargar Python para Windows desde la siguiente web https://www.python.org/downloads/windows/. Clica en el enlace "Latest Python 3 Release -Python x.x.x". Si tu ordenador ejecuta la versión de **64 bits** de Windows, descarga **Windows x86-64 executable installer**. De lo contrario, descarga **Windows x86 executable installer**. Después de descargar el instalador, deberías ejecutarlo (dándole doble click) y seguir las instrucciones. + +Una cosa para tener en cuenta: Durante la instalación, verás una ventana de "Setup". Make sure you tick the "Add Python {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![No te olvides de agregar Python al Path](../python_installation/images/python-installation-options.png) + +Cuando la instalación de complete, verás un cuadro de diálogo con un enlace que puedes seguir para saber más sobre Python o sobre la versión que has instalado. Cierra o cancela ese dialogo -- ¡Aprenderás más en ese tutorial! + +Nota: Si utilizas una versión antigua de Windows( 7, Vista u otra versión anterior) y el instalador{{ book.py_version }} Python falla con un error, entonces deberás instalar todas las actualizaciones de Windows e intentar instalar Python de nueva cuenta. Si aún así aparece el error, intenta instalar la version Python {{ book.py_min_release }} desde [python.org](https://www.python.org/downloads/windows/). + +> Django{{ book.django_version }}necesita Python{{ book.py_min_version }}o algo más avanzado, el cual no es compatible con Windows XP o versiones anteriores. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Descarga el archivo *Mac OS X 64-bit/32-bit installer*, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/es-ES/python_introduction/README.md b/es-ES/python_introduction/README.md new file mode 100644 index 00000000000..af54992a02f --- /dev/null +++ b/es-ES/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = ' ' %} + +# Introducción a Python + +> Parte de este capítulo se basa en tutoriales de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +¡Escribamos algo de código! + +## La Consola de Python + +> Para los lectores en casa: el video [conceptos básicos de Python: enteros, cadenas, listas, variables y errores](https://www.youtube.com/watch?v=MO63L4s-20U) cubre esta parte. + +Para empezar a jugar con Python, tenemos que abrir una *línea de comandos* en nuestra computadora. Deberías saber cómo hacerlo, pues lo aprendiste en el capítulo de [Introducción a la Línea de Comandos](../intro_to_command_line/README.md). + +Una vez que estés lista, sigue las instrucciones a continuación. + +Queremos abrir una consola de Python, así que escribe `python` en Windows o `python3` en Mac OS/Linux y pulsa `intro`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## ¡Tu primer comando en Python! + +Después de ejecutar el comando de Python, el cursor cambiará a `>>>`. Para nosotros esto significa que por ahora sólo podemos utilizar comandos del lenguaje Python. No tienes que escribir e`>>>` pues Python lo hará por ti. + +Si deseas salir de la consola de Python en cualquier momento, solo escribe `exit()` o usa el atajo `Ctrl + Z` para Windows y `Ctrl + D` para Mac/Linux. Luego no verás más `>>>`. + +Por ahora, no queremos salir de la consola de Python. Deseamos aprender más sobre ella. Vamos a comenzar escribiendo algo de matemática, escribe `2 + 3` y oprime la tecla `enter`. + +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +¡Qué bien! ¿Ves cómo salió la respuesta? ¡Python sabe matemática! Puedes probar otros comandos como: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +Para realizar una operación exponencial, digamos 2 elevado al cubo, escribimos: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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 puedes hacer… + +## Cadena de caracteres + +¿Qué tal tu nombre? Escribe tu nombre entre comillas, así: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" +'Ola' +``` + +¡Has creado tu primera cadena de texto! La misma es una secuencia de caracteres que puede ser procesada por una computadora. La cadena de texto (o string, en inglés) debe comenzar y terminar con el mismo carácter. Pueden ser comillas simples (`'`) o dobles (`"`) (¡no hay ninguna diferencia!) Las comillas le dicen a Python que lo que está dentro de ellas es una cadena de texto. + +Las cadenas pueden estar concatenadas. Prueba esto: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hola " + "Ola" +'Hola Ola' +``` + +También puedes multiplicar las cadenas por un número: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +Si necesitas poner un apóstrofe dentro de una cadena, hay dos formas de hacerlo. + +Usar comillas dobles: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +o escapar el apóstrofe con la diagonal inversa (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Bien, ¿eh? Para ver tu nombre en letras mayúsculas, escribe: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +¡Acabas de usar el **método** `upper` sobre tu cadena de texto! Un método (como `upper()`) es un conjunto de instrucciones que Python tiene que realizar sobre un objeto determinado (`"Ola"`) una vez que se le invoca. + +Si quieres saber el número de letras que contiene tu nombre, ¡también hay una **función** para eso! + +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +Te preguntarás ¿por qué a veces se invoca a las funciones con un `.` al final de una cadena (como `"Ola".upper()`) y a veces se invoca a la función colocando la cadena entre paréntesis? Bueno, en algunos casos las funciones pertenecen a los objetos, como `upper()`, que sólo puede ser utilizada sobre cadenas. En este caso, a la función le llamamos **método**. Otra veces, las funciones no pertenecen a ningún objeto específico y pueden ser usadas 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, es suficiente sobre las cadenas. Hasta ahora has aprendido sobre: + +- **la terminal** - teclear comandos (código) en 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 (cadenas de caracteres) para objetos de texto +- **operadores** - como `+` y `*`, combinan valores para producir uno nuevo +- **funciones** - como `upper()` y `len()`, ejecutan acciones sobre los objetos. + +Estos son los conocimientos básicos que puedes aprender de cualquier lenguaje de programación. ¿Lista para algo más difícil? ¡Seguro que lo estás! + +## Errores + +Vamos a intentar algo nuevo. ¿Podemos obtener la longitud de un número de la misma manera que pudimos averiguar la longitud de nuestro nombre? Escribe `len(304023)` y pulsa `enter`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +¡Pues tenemos nuestro primer error! El icono de {{ warning_icon }} es nuestra manera de darte un aviso de que el código que estás ejecutando no funciona como se espera. ¡Cometer errores (incluso algunos intencionales) son una parte importante del aprendizaje! + +Dicho error dice que los objetos de tipo "int" (números enteros) no tienen longitud. ¿Qué podemos hacer ahora? ¿Quizás podamos escribir el número como una cadena? Las cadenas tienen longitud, ¿verdad? + +{% filename %}command-line{% endfilename %} + +```python +>>> len(str(304023)) +6 +``` + +¡Funcionó! Hemos utilizado la función `str` dentro de la función `len`. `str()` convierte todo en cadenas de texto. + +- La función `str` convierte cosas en cadenas, **strings** +- La función `int` convierte cosas en enteros, **integers** + +> Importante: podemos convertir números en texto, pero no necesariamente podemos convertir texto en números - ¿qué sería `int('hello')`? + +## Variables + +Un concepto importante en la programación son las variables. Una variable no es más que un nombre para algo, de forma que puedas usarlo más tarde. Los programadores usan estas variables para almacenar datos, hacer su código más legible y para no tener que recordar qué es cada cosa. + +Supongamos que queremos crear una nueva variable llamada `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +Tecleamos que nombre es igual a Ola. + +Como habrás notado, tu programa no devolvió nada como lo hacía antes. Así que ¿cómo sabemos que la variable existe realmente? Escribe `name` y pulsa `intro`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +¡Genial! ¡Tu primera variable :)! Siempre puedes cambiar a lo que se refiere: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +También puedes usarla dentro de funciones: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Increíble, ¿verdad? Por supuesto, las variables pueden ser cualquier cosa, ¡también números! Prueba esto: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +Pero ¿qué pasa si usamos el nombre equivocado? ¿Puedes adivinar qué pasaría? ¡Vamos a probar! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): +  File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +¡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 un rato y descubre qué puedes hacer! + +## La función print + +Intenta esto: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` + +Cuando sólo escribes `name`, el intérprete de Python responde con la *representación* en forma de cadena 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 más claro. + +Como veremos después, `print()` también es útil cuando queremos imprimir cosas desde adentro de las funciones, o cuando queremos imprimir cosas en múltiples líneas. + +## Listas + +Además de cadenas y enteros, Python tiene toda clase de tipos de objetos diferentes. Ahora vamos a introducir uno llamado **list**. Las listas son exactamente lo que piensas que son: objetos que son listas de otros objetos. :) + +Anímate y crea una lista: + +{% filename %}command-line{% endfilename %} + +```python +>>> [] +[] +``` + +Sí, esta lista está vacía. No es muy útil, ¿verdad? Vamos a crear una lista de números de lotería. No queremos repetirnos todo el rato, así que la pondremos también en una variable: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +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 lo sabes! + +{% filename %}command-line{% endfilename %} + +```python +>>> len(lottery) +6 +``` + +¡Sí! `len()` puede darte el número de objetos en una lista. Útil, ¿verdad? Tal vez la ordenemos ahora: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.sort() +``` + +No devuelve nada, sólo ha cambiado el orden en que los números aparecen en la lista. Vamos a imprimirla otra vez y ver que ha pasado: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +Como puedes ver, los números de tu lista ahora están ordenados de menor a mayor. ¡Enhorabuena! + +¿Te gustaría invertir ese orden? ¡Vamos a hacerlo! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +Si quieres añadir algo a tu lista, puedes hacerlo escribiendo este comando: + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +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. Las programadoras y los programadores prefieren comenzar a contar desde 0, por lo tanto el primer objeto en tu lista esta en el indice 0, el próximo esta en el 1, y así sucesivamente. Intenta esto: + +{% filename %}command-line{% endfilename %} + +```python +>>> 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. + +Para borrar algo de tu lista tendrás que usar **índices** como aprendimos anteriormente y la función `pop()`. Vamos a tratar de ejemplificar esto y reforzaar lo que aprendimos anteriormente; vamos a borrar el primer número de nuestra lista. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +Funcionó de maravilla! + +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 para listas en este capítulo de la documentación de Python: https://docs.python.org/3/tutorial/datastructures.html + +## Diccionarios + +> Para lectores en casa: este capítulo está cubierto en el video [Bases de Python: Diccionarios](https://www.youtube.com/watch?v=ZX1CVvZLE6c). + +Un diccionario es similar a una lista, pero accedes a valores usando una llave en vez de un índice. Una llave puede ser cualquier cadena o número. La sintaxis para definir un diccionario vacío es: + +{% filename %}command-line{% endfilename %} + +```python +>>> {} +{} +``` + +Esto demuestra que acabas de crear un diccionario vacío. ¡Hurra! + +Ahora, trata escribiendo el siguiente comando (intenta reemplazando con tu propia información): + +{% filename %}command-line{% endfilename %} + +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` + +Con este comando, acabas de crear una variable llamada `participant` con tres pares llave-valor: + +- La llave `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 ella). + +Puedes verificar el contenido de claves individuales con esta sintaxis: + +{% filename %}command-line{% endfilename %} + +```python +>>> print(participant['name']) +Ola +``` + +Lo ves, es similar a una lista. Pero no necesitas recordar el índice - sólo el nombre. + +¿Qué pasa si le pedimos a Python el valor de una clave que no existe? ¿Puedes adivinar? ¡Pruébalo y verás! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 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. + +¿Cuando deberías usar un diccionario o una lista? Bueno, es un buen punto para reflexionar. Piensa sobre la respuesta, antes de mirar una solución en la siguiente línea. + +- ¿Sólo necesitas una secuencia ordenada de elementos? Usa una lista. +- ¿Necesitas asociar valores con claves, así puedes buscarlos eficientemente (usando las claves) más adelante? Utiliza un diccionario. + +Los diccionarios, como las listas, son *mutables*, lo que quiere decir que pueden ser modificados después de ser creados. Puedes agregar nuevos pares llave/valor a un diccionario luego de crearlo, como: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +Espero tenga sentido hasta ahora. :) ¿Listo para más diversión con diccionarios? Salta a la siguiente línea para algunas cosas sorprendentes. + +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'`, tienes que escribir el siguiente comando: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Como puedes ver en la salida, el par de llave-valor correspondiente a la llave 'favorite_numbers' ha sido eliminado. + +Además de esto, también puedes cambiar un valor asociado a una llave ya creada en el diccionario. Escribe: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Como puedes ver, el valor de la llave `'country'` ha sido modificado de `'Poland'` a `'Germany'`. :) ¿Emocionante? ¡Hurra! Has aprendido otra cosa asombrosa. + +### Resumen + +¡Genial! Sabes mucho sobre programación ahora. En esta última parte aprendiste sobre: + +- **errores** - ahora sabes cómo leer y entender los errores que aparecen si Python no entiende un comando +- **variables** - nombres para los objetos que te permiten codificar más fácilmente y hacer el código más legible +- **listas** - listas de objetos almacenados en un orden determinado +- **diccionarios** - objetos almacenados como pares llave-valor + +¿Emocionada por la siguiente parte? :) + +## Compara cosas + +> Para lectores en casa: este capítulo está cubierto en el video [Bases de Python: Comparaciones](https://www.youtube.com/watch?v=7bzxqIKYgf4). + +Buena 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. Nice, huh? + +¿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. + +Da dos tareas más a Python: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +Hemos visto `>` y `<`, pero, ¿qué significan `>=` y `<=`? Los puedes leer así: + +- x `>` y significa: x es mayor que y +- x `<` y significa: x es menor que 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 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? + +- **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: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and 'str' +``` + +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 + +Incidentalmente, acabas de aprender sobre un nuevo tipo de objeto en Python. Se llama **Boolean** (booleano). + +Hay sólo dos objetos booleanos: + +- True - verdadero +- False - falso + +Pero para que Python entienda esto, siempre los tienes que escribir de modo 'True' (la primera letra en mayúscula, con el resto de las letras en minúscula). **true, TRUE, y tRUE no funcionarán – solamente True es correcta.** (Lo mismo aplica también para 'False'.) + +Los valores booleanos pueden ser variables, también. Ve el siguiente ejemplo: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +También puedes hacerlo de esta manera: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +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 booleanos son una de las funciones más geniales en programación y acabas de aprender cómo usarlos. + +# ¡Guárdalo! + +> Para lectores en casa: este capítulo está cubierto en el video [Bases de Python: Guardando archivos y condicionales](https://www.youtube.com/watch?v=dOAg6QVAxyk). + +Hasta ahora hemos escrito todo nuestro código Python en el intérprete, lo cual nos limita a ingresar 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 +- ¡Ejecutarlo! + +Para salir del intérprete de Python que hemos estado usando, escribe `exit()` + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` + +Esto te llevará de vuelta a la línea de comandos. + +Anteriormente, seleccionamos un editor de código de la sección editor de código. Necesitaremos abrir el editor ahora y escribir algo de código en un nuevo archivo (o si está usando un Chromebook, cree un nuevo archivo en el IDE de la nube y abra el archivo, que estará en el editor de código incluido): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +Obviamente, ahora eres una desarrolladora Python muy experimentada, asi que sintete libre de escribir algo del código que has aprendido hoy. + +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 como queramos, pero la parte importante es asegurarse de que termina en **.py**. La extensión **.py** le dice a nuestro sistema operativo que es un **archivo ejecutable de python** y Python lo puede ejecutar. + +> **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, ahora deberías ver que la función `print` es de un color diferente a la cadena en su interior. Esto de denomina "sintaxis resaltada", y es una característica muy útil cuando se programa. El color de las cosas te dará pistas, como cadenas no cerradas o errores tipográficos en un nombre clave (como `def` en una función, que veremos a continuación). Esta es una de las razones por las cuales usar un editor de código. :) + +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 una Mac, el comando se verá algo como esto: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +En Linux, será así: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Recuerde que la palabra "Desktop" puede traducirse a su idioma local.) + + + + + +En la consola de Windows, ésto será como: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +Y en Windows Powershell, será así: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +Si tú estás atascada, pregunta por ayuda. ¡Eso es exactamente lo que hacen los entrenadores! + +Ahora usa Python para ejecutar el código en el archivo como esto: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hello, Django girls! + + +Nota: en Windows 'python3' no es reconocido como un comando. En su lugar, usa 'python' para ejecutar el archivo: + +{% filename %}command-line{% endfilename %} + +```python +> python python_intro.py +``` + +¡Correcto! Ahora corriste tu primer programa de Python que fue guardado en un archivo. ¿Se siente increíble? + +Puedes ahora moverte a una herramienta esencial en programación: + +## If … elif … else + +Muchas de las cosas en código debería ser ejecutadas solo cuando las condiciones son conocidas. Eso es por qué Python lo ha llamado **sentencias if**. + +Reemplaza el código en tu archivo **python_intro.py** con esto: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: +``` + +Si guardáramos y corriéramos esto, veríamos un error como éste: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +Python nos espera dar nuevas instrucciones, las cuales son ejecutadas si la condición `3 > 2` torna a ser verdadera (o `True` para ese caso). Intentemos imprimir en Python "¡Funciona!". Cambia el código de tu archivo **python_intro.py** a esto: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: + print('It works!') +``` + +¿Notas cómo estamos indentando la siguiente línea de código con 4 espacios? Nosotros necesitamos hacer ésto para que Python comprenda que el código se ejecuta si el resultado es verdadero. Tú puedes hacer un espacio, pero prácticamente todos los programadores en Python hacen 4 espacios para hacer el código más legible. Un simple tabulador también contará como 4 espacios tan largos como tu editor de texto esté configurado. Cuando tú haces tu elección, ¡no la cambies! Si tu ya identaste con 4 espacios, sigue haciendo futuras identaciones con 4 espacios también, de otra forma, tú puedes correr con problemas. + +Guárdalo y ejecútalo de nuevo: + +{% filename %}command-line{% endfilename %} + +```python +$ python3 python_intro.py +It works! +``` + +Nota: Recuerda que en Windows, 'python3' no es reconocido como un comando. Desde ahora, reemplaza 'python3' con 'python' para ejecutar el archivo. + +### ¿Qué pasa si una condición no es verdadera? + +En previos ejemplos, el código fue ejecutado solamente cuando las condiciones eran Verdaderas. Pero Python también tiene sentencias `elif` y `else`: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 5 > 2: + print('5 is indeed greater than 2') +else: + print('5 is not greater than 2') +``` + +Cuando ésto se ejecuta, imprimirá: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +Si 2 era mayor que el número 5, entonces el segundo comando sería ejecutado. Veamos cómo `elif` funciona: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +y ejecuta: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hey Sonja! + + +¿Ves qué sucedió allí? `elif` te deja añadir condiciones adicionales que se ejecutan si las condiciones previas fallan. + +Tú puedes añadir tantas sentencias `elif` como quieras, luego de tu sentencia inicial `if`. Por ejemplo: + +{% 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("Me duelen las orejas! :(") +``` + +Python corre a través de cada prueba secuencialmente e imprime: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Perfect, I can hear all the details + + +## Comentarios + +Los comentarios son líneas que comienzan con `#`. Tú puedes escribir lo que quieras luego de el `#` y Python lo ignorará. Los comentarios pueden hacer que el código sea más fácil de entender para otras personas. + +Veamos cómo luce: + +{% filename %}python_intro.py{% endfilename %} + +```python +# Cambiar el volumen si esta muy alto o muy bajo +if volume < 20 or volume > 80: + volume = 50 + print("Mucho mejor!") +``` + +Tú no necesitas escribir un comentario para cada línea de código, pero ellos son útiles para explicar qué está haciendo el código, o proveer un resumen cuando se está haciendo algo complejo. + +### Resumen + +En los últimos ejercicios tú aprendiste acerca de: + +- **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 para que puedas ejecutar programas más grandes. +- **if... elif... else** - sentencias que te permiten ejecutar código sólo cuando se cumplen ciertas condiciones. +- **comentarios** - líneas que Python no ejecutará que permiten documentar el código + +¡Es tiempo para leer la última parte de éste capítulo! + +## ¡Tus propias funciones! + +> Para lectores en casa: este capítulo está cubierto en el video [Bases de Python: Funciones](https://www.youtube.com/watch?v=5owr-6suOl0). + +¿Recuerdas las funciones como `len()` que puedes ejecutar en Python? Bien, buenas noticias - ¡tú aprenderás cómo escribir tus propias funciones ahora! + +Una función es una secuencia de instrucciones que Python debería ejecutar. Cada función en Python inicia con la palabra clave `def`, el nombre es dado, y puede tener algunos parámetros. Veamos. Reemplaza el código en **python_intro.py** con lo siguiente: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, ¡nuestra primera función está lista! + +Tú puedes preguntar por qué hemos escrito el nombre de la función en la parte inferior de el archivo. Cuando escribimos `def hi():` y las líneas indentadas que siguen, estamos escribiendo instrucciones que la función `hi()` debe hacer. Python leerá y recordará estas instrucciones, pero no ejecutará la función todavía. Para decirle a Python que queremos ejecutar la función, tenemos que llamar a la función con `hi()`. Python lee el archivo y lo ejecuta desde arriba hacia abajo, así que tenemos que definir la función en el archivo antes de llamarla. + +Ejecuta ésto ahora y ve qué sucede: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Nota: si ésto no funciona, ¡Tranquil@! La salida te ayudará a entender por qué: + +- Si te sale `NameError`, probablemente significa que escribiste algo mal, así que deberias comprobar si utilizaste el mismo nombre para crear la función con `def hi():` y al llamarla con `hi()`. +- Si te sale un `IndentationError`, comprueba que las líneas del `print` tienen el mismo espacio en blanco al comienzo de línea: python requiere que todo el código dentro de la función esté perfectamente alineado. +- Si no hay ninguna salida, comprueba que el último `hi()` *no esté* identado - si lo está, esa línea también sera parte de la función, y nunca se ejecutará. + +Construyamos nuestra primera función con parámetros. Cambiarémos el ejemplo anterior - una función que dice 'hola' para la persona que lo ejecuta - con un nombre: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): +``` + +Como puedes ver, ahora le dimos a nuestra función un parámetro que llamamos `nombre`: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +hi() +``` + +Recuerda: La función `print` está indentada con 4 espacios en la sentencia `if`. Esto es porque la función se ejecuta cuando la condición es conocida. Veamos cómo funciona ahora: + +{% filename %}{{ warning_icon }} 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, un error. Por suerte, Python nos da un útil y agradable mensaje de error. Este nos dice que la función `hi()` (que definimos) tiene un argumento requerido (llamado `nombre`) y que olvidamos pasarlo cuando llamamos a la función. Configuremos esto en la parte inferior del archivo: + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Ola") +``` + +Y ejecutemos otra vés: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Ola! + + +¿Y si cambiamos el nombre? + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Sonja") +``` + +Y lo ejecutamos: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Sonja! + + +Ahora, ¿Qué piensas que sucederá si escribes otro nombre allí? (No Ola o Sonja.) Intenta y ve si estás en lo correcto. Debería imprimir esto: + +{% filename %}command-line{% endfilename %} + + Hi anonymous! + + +Esto es sorprendente, ¿Verdad? De esta manera tú no tienes que repetir la función cada vez que cambies el nombre de la persona que está supuesta a recibir. Y eso es exactamente por qué necesitamos funciones - ¡tú nunca quieres repetir tú código! + +Hacer algo más inteligente - hay más nombres que dos, y escribir una condición para cada uno sería difícil, ¿Verdad? Reemplaza el contenido de tu archivo con lo siguiente: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Llamarémos al código ahora: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + + +¡Felicidades! ¡Ya aprendíste a cómo escribir funciones! :) + +## Bucles + +> Para lectores en casa: este capítulo está cubierto en el video [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0). + +Listo ésta es la última parte. Eso fue rápido, ¿verdad? :) + +Los programadores no les gusta repetir. Programar es todo acerca de automatizar cosas, así que no queremos recibir a cada persona por su nombre manualmente, ¿verdad? Allí es dónde los ciclos vienen a manejarse. + +¿Aún recuerdas las listas? Hagamos una lista de niñas: + +{% filename %}python_intro.py{% endfilename %} + +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + +Queremos recibir a todos ellos con sus nombres. Tenemos la función `hola` para hacerlo, así que usémosla en un ciclo: + +{% filename %}python_intro.py{% endfilename %} + +```python +for name in girls: +``` + +La sentencia `for` se comporta parecido a una sentencia `if`; ambos códigos necesitan ser indentados por 4 espacios. + +Aquí está completo el código que estará en el archivo: + +{% filename %}python_intro.py{% endfilename %} + +```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 ejecutemos: + +{% 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 + + +Como puedes ver, todo lo que coloques dentro de una sentencia `for` con una indentación, será repetida para cada elemento de la lista `girls`. + +Tu puedes también usar `for` con números usando la función `range`: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +El cuál imprimirá: + +{% filename %}command-line{% endfilename %} + + 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). + +Nota que el segundo de estos números no está incluido en la lista que regresa Python (es decir, `range(1, 6)` cuenta desde 1 a 5, pero no incluye el número 6). Esto es porque "range" está medio-abierto, y por eso se incluye el primer valor, pero no el último. + +## Resumen + +Eso es todo. **¡Tú rockeas totalmente!** Esto fue un capítulo difícil, así que deberías sentirte orgullos@ de ti. ¡Estamos definitivamente encantados de que hayas llegado tan lejos! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +Tu podrías querer un momento para algo - estirarte, caminar cerca, descansar tus ojos - antes de avanzar a un próximo capítulo. :) + +![Pastelillo](images/cupcake.png) \ No newline at end of file diff --git a/es-ES/signup_pythonanywhere.md b/es-ES/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/es-ES/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/es-ES/template_extending/README.md b/es-ES/template_extending/README.md new file mode 100644 index 00000000000..4fe42b329b8 --- /dev/null +++ b/es-ES/template_extending/README.md @@ -0,0 +1,151 @@ +# Extendiendo plantillas + +Otra cosa buena que tiene Django es la **extensión de plantillas**. ¿Qué significa? Significa que puedes reusar partes del HTML para diferentes páginas del sitio web. + +Las plantillas son útiles cuando quieres utilizar la misma información o el mismo diseño en más de un lugar. No tienes que repetirte a ti misma en cada archivo. Y si quieres cambiar algo, no tienes que hacerlo en cada plantilla, sólo en una! + +## Crea una plantilla base + +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/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +Ahora, ábrelo en el editor de código y copia todo el contenido de `post_list.html` en `base.html`, así: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Blog de Django Girls + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Luego, en `base.html` reemplaza por completo tu `` (todo lo que haya entre `` and ``) con esto: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}Seguro que ya te has dado cuenta de que lo que hemos hecho ha sido cambiar todo lo que había entre `{% for post in posts %}` y `{% endfor %}` por {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +Pero ¿por qué? ¡Acabas de crear un bloque! Hemos usado la etiqueta de plantilla `{% block %}` para crear un área en la que se insertará HTML. Ese HTML vendrá de otra plantilla que extiende esta (`base.html`). Enseguida te enseñamos cómo se hace. + +Ahora guarda `base.html` y abre `blog/templates/blog/post_list.html` de nuevo en el editor. {% raw %}Quita todo lo que hay encima de `{% for post in posts %}` y por debajo de `{% endfor %}`. Cuando termines, el archivo tendrá este aspecto:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +Queremos utilizar esto como parte de nuestra plantilla en los bloques de contenido. ¡Es hora de añadir etiquetas de bloque en este archivo! + +{% raw %}Tu etiqueta de bloque debe ser la misma que la etiqueta del archivo `base.html`. También querrás que incluya todo el código que va en los bloques de contenido. Para ello, pon todo entre `{% block content %}` y `{% endblock %}`. Algo como esto:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Solo falta una cosa. Tenemos que conectar estas dos plantillas. ¿Esto es lo que significa extender plantillas! Para eso tenemos que añadir una etiqueta "extends" al comienzo del archivo. Así: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +¡Y ya está! Guarda el fichero y comprueba que el sitio web sigue funcionando como antes. :) + +> Si te sale el error `TemplateDoesNotExist`, que significa que no hay ningún archivo `blog/base.html` y tienes `runserver` corriendo en la consola. Intenta pararlo, pulsando Ctrl+C (teclas Control y C a la vez) en la consola y reiniciarlo con el comando `python manage.py runserver`. \ No newline at end of file diff --git a/es-ES/whats_next/README.md b/es-ES/whats_next/README.md new file mode 100644 index 00000000000..bf6a19a94f4 --- /dev/null +++ b/es-ES/whats_next/README.md @@ -0,0 +1,43 @@ +# ¿Y ahora qué? + +Date muchas felicitaciones. **¡Eres increíble!** ¡Estamos orgullosas! <3 + +### ¿Qué hacer ahora? + +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](http://facebook.com/djangogirls) o [Twitter](https://twitter.com/djangogirls) para estar al día. + +### ¿Me puedes recomendar recursos adicionales? + +¡ Sí! Hay un *montón* de recursos en línea para el aprendizaje de todas las clases de habilidades en programación – puede ser algo intimidante donde ir, pero le tenemos cubierto. Cualquiera que sean tus intereses antes de que usted viniera a Django Girls, y los intereses que haya desarrollado a lo largo del tutorial, aquí hay algunos recursos gratuitos (o recursos con grandes componentes libres) que puede utilizar para llegar a donde quiera estar. + +#### Django + +- En nuestro libro [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [El tutorial oficial de Django](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Comienza a usar las lecciones en video de Django](http://www.gettingstartedwithdjango.com/) +- [Especialización de Django para todos](https://www.coursera.org/specializations/django) - algunas vídeo-lecturas pueden ser auditadas de manera gratuita y puedes ganar un certificado de Coursera por tomar estos cursos + +#### HTML, CSS y JavaScript + +- [El curso de desarrollo web de Codeacademy](https://www.codecademy.com/learn/paths/web-development) +- [FreeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [El curso de Python en Codeacademy](https://www.codecademy.com/learn/learn-python) +- [Curso de Python de Google](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – Los primeros ejercicios son gratuitos +- [Nuevos tutoriales de Coder](http://newcoder.io/tutorials/) - esta es una variedad de ejemplos prácticos de cómo puedes usar Python +- [edX](https://www.edx.org/course?search_query=python) – puedes auditar la mayoría de los cursos gratis, pero si desea un certificado o créditos para una calificación de educación superior, entonces eso costará dinero +- [La especialización Python en Coursera](https://www.coursera.org/specializations/python) – algunas videoconferencias pueden ser auditadas gratuitamente y puedes ganar un certificado de Coursera tomando estos cursos +- [Python for Everybody](https://www.py4e.com/) - una versión libre y abierta de la especialización de Python en Coursera + +#### Trabajar con datos + +- [Curso de ciencia de datos de Codecademy](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – puedes auditar la mayoría de los cursos gratis, pero si desea un certificado o créditos para una calificación de educación superior, entonces eso costará dinero +- [Dataquest](https://www.dataquest.io/) – las primeras 30 "misiones" son gratuitas + +¡No podemos esperar para ver lo que construyes a continuación! \ No newline at end of file diff --git a/es/GLOSSARY.md b/es/GLOSSARY.md new file mode 100644 index 00000000000..2e928dda548 --- /dev/null +++ b/es/GLOSSARY.md @@ -0,0 +1,3 @@ +# code editor + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/es/README.md b/es/README.md index f701e82f95b..01736ae0502 100755 --- a/es/README.md +++ b/es/README.md @@ -1,51 +1,51 @@ -# Tutorial de Django Girls +# 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) +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) -> 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/ +> 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/ -## Translation -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. +## Welcome -## Introducción +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. -¿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? +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) -Bueno, ¡tenemos buenas noticias para ti! Programar no es tan difícil como aparenta y queremos mostrarte cuán divertido puede llegar a ser. +## Introduction -Este tutorial no te convertirá en programador mágicamente. Si quieres ser buena en esto, necesitarás meses o incluso 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. +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? -¡Esperamos poder hacerte amar la tecnología tanto como nosotras lo hacemos! +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. -## ¿Qué aprenderás con este tutorial? +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. -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! +We hope that we'll be able to make you love technology as much as we do! -Tendrá (más o menos) ésta apariencia: +## What will you learn during the tutorial? -![Figura 0.1][2] +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! - [2]: images/application.png +It will (more or less) look like this: -> 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í! +![Figure 0.1](images/application.png) -Bien, [empecemos por el principio...][3] +> 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! - [3]: ./how_the_internet_works/README.md +OK, [let's start at the beginning…](./how_the_internet_works/README.md) -## Sobre nosotros y cómo contribuir +## Following the tutorial at home -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]. +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. - [4]: https://djangogirls.org/ - [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md +In every chapter already covered, there is a link that points to the correct video. -## ¿Te gustaría ayudarnos a traducir el tutorial a otros idiomas? +## About and contributing -Actualmente, las traducciones se llevan a cabo sobre la plataforma crowdin.com en: +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). -https://crowdin.com/project/django-girls-tutorial +## Would you like to help us translate the tutorial into other languages? + +Currently, translations are being kept on crowdin.com platform at: -Si tu idioma no esta listado en crowdin, por favor [abre un nuevo problema][6] informando el idioma así podemos agregarlo. +https://crowdin.com/project/django-girls-tutorial - [6]: https://github.com/DjangoGirls/tutorial/issues/new +If your language is not listed on [crowdin](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/es/SUMMARY.md b/es/SUMMARY.md index 31ea84b15ed..7a45700a27d 100755 --- a/es/SUMMARY.md +++ b/es/SUMMARY.md @@ -1,25 +1,27 @@ -# Índice +# Summary -* [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) -* [¿Qué sigue?](whats_next/README.md) +* [Introduction](README.md) +* [Installation](installation/README.md) +* [Installation (chromebook)](chromebook_setup/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) +* [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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [What's next?](whats_next/README.md) \ No newline at end of file diff --git a/es/chromebook_setup/README.md b/es/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/es/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/es/chromebook_setup/instructions.md b/es/chromebook_setup/instructions.md new file mode 100644 index 00000000000..809281456d3 --- /dev/null +++ b/es/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/es/code_editor/README.md b/es/code_editor/README.md index 3f6c86b1f73..404011f1b7d 100755 --- a/es/code_editor/README.md +++ b/es/code_editor/README.md @@ -1,43 +1,11 @@ -# Editor de código +# Code editor -Estás a punto de escribir tu primera línea de código, así que ¡es hora de descargar un editor de código! +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. -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. +You're about to write your first line of code, so it's time to download a code editor! -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. +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** You might have done this earlier in the Installation chapter – if so, you can skip right ahead to the next chapter! -## Gedit - -Gedit es un editor de código abierto, gratis, disponible para todos los sistemas operativos. - -[Descárgalo aquí][1] - - [1]: https://wiki.gnome.org/Apps/Gedit#Download - -## 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]: 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. Está disponible para Windows, OSX y Linux. - - [3]: https://github.com/ - -[Descárgalo aquí][4] - - [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 +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/es/code_editor/instructions.md b/es/code_editor/instructions.md new file mode 100644 index 00000000000..074cd86196e --- /dev/null +++ b/es/code_editor/instructions.md @@ -0,0 +1,31 @@ +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 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 and 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. :) \ No newline at end of file diff --git a/es/css/README.md b/es/css/README.md index f252d90e6a3..04d5996ae52 100755 --- a/es/css/README.md +++ b/es/css/README.md @@ -1,58 +1,59 @@ -# CSS - ¡Hazlo bonito! +# CSS – make it pretty! -Nuestro blog todavía se ve bastante feo, ¿verdad? ¡Es hora de hacerlo bonito! Vamos a usar CSS para eso. +Our blog still looks pretty ugly, right? Time to make it nice! We will use CSS for that. -## ¿Qué es CSS? +## What is 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 ;). +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. ;) -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. +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. -## ¡Vamos a usar Bootstrap! +## Let's use Bootstrap! -Bootstrap es uno de los frameworks HTML y CSS más populares para desarrollar webs bonitas: https://getbootstrap.com/ +Bootstrap is one of the most popular HTML and CSS frameworks for developing beautiful websites: https://getbootstrap.com/ -Lo escribieron programadores que trabajaban para Twitter y ahora lo desarrollan voluntarios de todo el mundo. +It was written by programmers who worked for Twitter. Now it's developed by volunteers from all over the world! -## Instalar Bootstrap +## Install Bootstrap -Para instalar Bootstrap tienes que añadir esto al `` de tu fichero `.html` (`blog/templates/blog/post_list.html`): +To install Bootstrap, you need to add this to your `` in your `.html` file: -```html - - -``` +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -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á! +```html + + +``` -![Figure 14.1][1] +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! - [1]: images/bootstrap1.png +![Figure 14.1](images/bootstrap1.png) -¡Se ve mucho mejor! +Looking nicer already! -## Ficheros estáticos en Django +## Static files in Django -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. +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. -### Dónde poner los ficheros estáticos para Django +### Where to put static files for 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`. +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`. -Esto lo conseguimos creando una carpeta llamada `static` dentro de la aplicación blog: +We do that by creating a folder called `static` inside the blog app: djangogirls ├── blog │ ├── migrations - │ └── static + │ ├── static + │   └── templates └── mysite -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. +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. -## ¡Tu primer fichero CSS! +## Your first CSS file! -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? +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 @@ -61,234 +62,243 @@ Crea un nuevo directorio llamado `css` dentro de tu directorio `static`. Para a └─── blog.css -¡Es hora de escribir algo de CSS! Abre el fichero `blog/static/css/blog.css` en tu editor de código. - -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. +Time to write some CSS! Open up the `blog/static/css/blog.css` file in your code editor. - [2]: https://www.codecademy.com/tracks/web +We won't be going too deep into customizing and learning about CSS here. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. -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`. +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`. - [3]: http://www.w3schools.com/cssref/css_colornames.asp +In your `blog/static/css/blog.css` file you should add the following code: -En tu fichero `blog/static/css/blog.css` deberías añadir el siguiente código: +{% filename %}blog/static/css/blog.css{% endfilename %} ```css - h1 a { - color: #FCA205; - } -``` +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 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! -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`: +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 - -``` + +``` -Puedes leer más sobre [selectores de CSS en w3schools][4]. +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). - [4]: http://www.w3schools.com/cssref/css_selectors.asp +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: -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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - {% load staticfiles %} -``` +{% load staticfiles %} +``` -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: +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 be overriden by code in Bootstrap files. We just told our template where our CSS file is located. -Le acabamos de decir a nuestra plantilla dónde se encuentra nuestro fichero CSS. +Your file should now look like this: -Ahora tu fichero debería tener este aspecto: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - {% load staticfiles %} - - - Django Girls blog - - - - - +{% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %}
-

Django Girls Blog

+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

- - {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

-
- {% endfor %} - - -``` + {% endfor %} + + +``` -De acuerdo, ¡guarda el fichero y actualiza el sitio! +OK, save the file and refresh the site! -![Figure 14.2][5] +![Figure 14.2](images/color2.png) - [5]: images/color2.png +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! -¡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! +{% filename %}blog/static/css/blog.css{% endfilename %} ```css - body { - padding-left: 15px; - } -``` +body { + padding-left: 15px; +} +``` -Añade esto a tu CSS, guarda el fichero y ¡mira cómo funciona! +Add that to your CSS, save the file and see how it works! -![Figure 14.3][6] +![Figure 14.3](images/margin2.png) - [6]: images/margin2.png +Maybe we can customize the font in our header? Paste this into your `` in `blog/templates/blog/post_list.html` file: -¿Quizá podríamos personalizar la tipografía del título? Pega esto en la sección `` del fichero `blog/templates/blog/post_list.html`: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - -``` + +``` + +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). -Esta línea va a importar una tipografía llamada *Lobster* de Google Fonts (https://www.google.com/fonts). +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: -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: +{% filename %}blog/static/css/blog.css{% endfilename %} ```css - h1 a { - color: #FCA205; - font-family: 'Lobster'; - } -``` +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` -![Figure 14.3][7] +![Figure 14.3](images/font.png) - [7]: images/font.png +Great! -¡Genial! +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. -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. +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: -¡Adelante! Nombra algunas partes del código HTML. Añade una clase llamada `page-header` al `div` que contiene el encabezado, así: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - -``` + +``` + +And now add a class `post` to your `div` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -Y ahora añade la clase `post` al `div` que contiene una entrada del blog. +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html +{% for post in posts %}

published: {{ post.published_date }}

{{ post.title }}

{{ 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`: +in the `blog/templates/blog/post_list.html` with this: -```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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - {% 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 }}

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

published: {{ post.published_date }}

- {% endfor %} -
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %}
-``` - -Guarda los ficheros y actualiza tu sitio. +
+``` -![Figure 14.4][8] +Save those files and refresh your website. - [8]: images/final.png +![Figure 14.4](images/final.png) -¡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. +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? -No tengas miedo de jugar un poco con este CSS e intentar cambiar algunas cosas. Si rompes algo, no te preocupes, ¡siempre puedes deshacerlo! +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! -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. +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. -¡¿Lista para el siguiente capítulo?! :) +Ready for the next chapter?! :) \ No newline at end of file diff --git a/es/deploy/README.md b/es/deploy/README.md index c85530aff05..b44e2eaaf73 100755 --- a/es/deploy/README.md +++ b/es/deploy/README.md @@ -1,72 +1,59 @@ -# ¡Despliega! +# Deploy! -> **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. +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. -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 :). +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) -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. +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. - [1]: https://pythonanywhere.com/ +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! -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! - - [2]: https://www.github.com - -Usaremos GitHub como paso intermedio para transportar nuestro código desde y hasta PythonAnywhere. +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. # Git -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. - -## Instalar Git - -### Windows +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. -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. +{% include "/deploy/install_git.md" %} - [3]: https://git-scm.com/ +## Starting our Git repository -### MacOS +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: -Descarga Git de [git-scm.com][3] y sigue las instrucciones. +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. -### Linux - -Si no lo tienes ya instalado, git debería estar disponible a través del administrador de paquetes, prueba con: - - sudo apt-get install git - # o - sudo yum install git - - -## Iniciar nuestro repositorio Git - -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`: - -> **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`. +{% filename %}command-line{% endfilename %} $ git init Initialized empty Git repository in ~/djangogirls/.git/ - $ git config user.name "Tu nombre" - $ git config user.email tú@ejemplo.com + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com -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) +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). -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: +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} *.pyc + *~ __pycache__ myvenv db.sqlite3 + /static .DS_Store -Y guárdalo como `.gitignore` en la primera carpeta "djangogirls". +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. -> **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. +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: -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: +{% filename %}command-line{% endfilename %} $ git status On branch master @@ -76,243 +63,198 @@ Es buena idea utilizar el comando `git status` antes de `git add` o cuando no es Untracked files: (use "git add ..." to include in what will be committed) - .gitignore - blog/ - manage.py - mysite/ + .gitignore + blog/ + manage.py + mysite/ nothing added to commit but untracked files present (use "git add" to track) -Y finalmente guardamos nuestros cambios. Ve a la consola y ejecuta estos comandos: +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} $ git add --all . - $ git commit -m "Mi app Django Girls, primer commit" + $ git commit -m "My Django Girls app, first commit" [...] 13 files changed, 200 insertions(+) create mode 100644 .gitignore [...] create mode 100644 mysite/wsgi.py + ``` - -## Enviar nuestro código a GitHub - -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". - - [4]: https://www.github.com - -![][5] - - [5]: images/new_github_repo.png - -> **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`. - -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: - -![][6] - - [6]: images/github_get_repo_url_screenshot.png - -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 - -Escribe tu nombre de usuario y contraseña de GitHub y deberías ver algo así: - - 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. + ## Pushing your code to GitHub - - - -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 :) - - [7]: https://github.com/django/django - [8]: https://github.com/DjangoGirls/tutorial - -# Configurar nuestro blog en PythonAnywhere - -Es hora de registrar una cuenta gratuita de tipo "Beginner" en PythonAnywhere. - -* [www.pythonanywhere.com][9] - - [9]: https://www.pythonanywhere.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. - -## Bajar nuestro código en PythonAnywhere - -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 - -> **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. - -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: - - $ git clone https://github.com//my-first-blog.git - -> **Nota**: No pongas los símbolos < y >, solo escribe tu usuario. - -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 + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) - -### Crear un virtualenv en PythonAnywhere - -Tal y como hiciste en tu propio ordenador, puedes crear un virtualenv en PythonAnywhere. En la consola Bash, escribe: - - 20:20 ~ $ cd my-first-blog + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. - 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 + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. - (myvenv)20:20 ~ $ pip install django==1.8 whitenoise - Collecting django - [...] - Successfully installed django-1.8 whitenoise-1.0.6 + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} - - -### Recopilar ficheros estáticos +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master -¿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. +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + -Aprenderemos un poco más sobre los ficheros estáticos más adelante, cuando editemos el CSS de nuestro sitio. +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 -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. +- [new branch] master -> master Branch master set up to track remote branch master from origin. - 20:20 ~ $ python manage.py collectstatic +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> - You have requested to collect static files at the destination - location as specified in your settings: + Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) - /home/edith/my-first-blog/static - This will overwrite existing files! - Are you sure you want to do this? + # Setting up our blog on PythonAnywhere - Type 'yes' to continue, or 'no' to cancel: yes + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. - -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... - - 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'. + {% include "/deploy/signup_pythonanywhere.md" %} - -### Crear la base de datos en PythonAnywhere - -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. - -Así que inicializamos la base de datos en el servidor igual que lo hicimos en nuestro ordenador, con `migrate` y `createsuperuser`: - - (myvenv)20:20 ~ $ python manage.py migrate - Operations to perform: - [...] - Applying sessions.0001_initial... OK + ## Pulling our code down on PythonAnywhere - (myvenv)20:20 ~ $ python manage.py createsuperuser + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} -## Publicar nuestro blog como una aplicación web - -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. - -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**. - -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. - -> **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 ;-) - -### Configurar el virtualenv +$ git clone https://github.com//my-first-blog.git -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. +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + -![][10] +$ 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 - [10]: images/pythonanywhere_web_tab_virtualenv.png +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + -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/` +$ cd my-first-blog -> **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 >! +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. -### Configurar el fichero WSGI +$ source myvenv/bin/activate -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. +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 -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. +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + -Elimina todo el contenido actual y reemplázalo con algo como esto: +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser -``` python +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python import os import sys - path = '/home//my-first-blog' # aquí utiliza tu propio usuario, sin los simbolos < y > + path = os.path.expanduser('~/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()) -``` + from django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. + +Hit **Save** and then go back to the **Web** tab. + +We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. + +## Debugging tips -> **Nota** no olvides sustituir tu propio nombre de usuario donde dice `` +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: -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". +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. -Dale a **Save** y vuelve a la pestaña **Web**. +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. -¡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. +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? -## Consejos de depuración +- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. -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 +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). -* 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? +And remember, your coach is here to help! -¡Tu tutor está ahí para ayudar! +# You are live! -# ¡Estás en vivo! +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. -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. +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? -*¡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! +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! \ No newline at end of file diff --git a/es/deploy/install_git.md b/es/deploy/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/es/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/es/deploy/signup_pythonanywhere.md b/es/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/es/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/es/django/README.md b/es/django/README.md index 782c575948f..c62c145305b 100755 --- a/es/django/README.md +++ b/es/django/README.md @@ -1,27 +1,27 @@ -# ¿Qué es Django? +# What is Django? -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. +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier. -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. +When you're building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, 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. +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. -Los frameworks existen para ahorrarte tener que reinventar la rueda y ayudarte a aliviar la carga cuando construyes un sitio. +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. -## ¿Por qué necesitas un framework? +## Why do you need a framework? -Para entender para que es Django, necesitamos mirar mas de cerca a los servidores. Lo primero es que el servidor necesita saber que quieres que te sirva una página web. +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. -Imagina un buzón (puerto) el cual es monitoreado por cartas entrantes (peticiones). Esto es realizado por un servidor web. El servidor web lee la carta, y envía una respuesta con una página web. Pero cuando quieres enviar algo, tienes que tener algún contenido. Y Django es algo que te ayuda a crear el contenido. +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. -## ¿Qué sucede cuando alguien solicita una página web de tu servidor? +## What happens when someone requests a website from your server? -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*). +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). -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! +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! -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. +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. -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. +Of course, the description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. -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! +So instead of diving too much into details, we will simply start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/es/django_admin/README.md b/es/django_admin/README.md index c340823c749..46a5afbb500 100755 --- a/es/django_admin/README.md +++ b/es/django_admin/README.md @@ -1,27 +1,40 @@ -# Administrador de Django +# Django admin -Para agregar, editar y borrar los posts que hemos modelado, utilizaremos el administrador de Django. +To add, edit and delete the posts we've just modeled, we will use Django admin. -Vamos a abrir el archivo `blog/admin.py` y reemplazar su contenido con esto: +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} ```python - from django.contrib import admin - from .models import Post - - admin.site.register(Post) +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)`. +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. -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: +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: -![Página de inicio de sesión][1] +![Login page](images/login_page2.png) - [1]: images/login_page2.png +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. -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): +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + Username: admin Email address: admin@admin.com Password: @@ -29,20 +42,16 @@ Para poder ingresar deberás crear un *superusuario* - un usuario que tiene cont Superuser created successfully. -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 +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. -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 :). +![Django admin](images/django_admin3.png) -Asegúrate de que por lo menos dos o tres posts (pero no todos) tienen la fecha de publicación. Será útil luego. +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) -![Administrador de Django][3] +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. - [3]: images/edit_post3.png +![Django admin](images/edit_post3.png) -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/ +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ -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! +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/es/django_forms/README.md b/es/django_forms/README.md index 1e4b404124e..1d9efebffe4 100755 --- a/es/django_forms/README.md +++ b/es/django_forms/README.md @@ -1,378 +1,447 @@ -# Formularios en Django +# Django Forms -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! +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! -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. +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. -Esto es exactamente lo que queremos hacer: crearemos un formulario para nuestro modelo `Post`. +This is exactly what we want to do: we will create a form for our `Post` model. -Como cada parte importante de Django, forms tienen su propio archivo: `forms.py`. +Like every important part of Django, forms have their own file: `forms.py`. -Tenemos que crear un archivo con este nombre en el directorio `blog`. +We need to create a file with this name in the `blog` directory. blog └── forms.py -Ok, vamos a abrirlo y vamos a escribir el siguiente código: - +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + ```python - from django import forms - - from .models import Post - - class PostForm(forms.ModelForm): - - class Meta: - model = Post - fields = ('title', 'text',) -``` +from django import forms -Primero necesitamos importar Django forms (`from django import forms`) y, obviamente, nuestro modelo `Post` (`from .models import 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. +class PostForm(forms.ModelForm): -A continuación, tenemos `class Meta`, donde le decimos a Django qué modelo debe utilizar para crear este formulario (`model = Post`). + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. -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? +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). -¡Y eso es todo! Todo lo que necesitamos hacer ahora es usar el formulario en una *view* y mostrarla en una plantilla. +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? -Una vez más vamos a crear: un enlace a la página, una dirección URL, una vista y una plantilla. +And that's it! All we need to do now is use the form in a *view* and display it in a template. -## Enlace a una página con el formulario +So once again we will create a link to the page, a URL, a view and a template. -Es hora de abrir `blog/templates/blog/base.html`. Vamos a añadir un enlace en `div` llamado `page-header`: +## Link to a page with the form + +It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html - -``` + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. -Ten en cuenta que queremos llamar a nuestra nueva vista `post_new`. +After adding the line, your HTML file should now look like this: -Después de agregar la línea, tu archivo html debería tener este aspecto: +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html - {% load staticfiles %} - - - Django Girls blog - - - - - - - -
-
-
- {% block content %} - {% endblock %} -
+{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %}
- - -``` +
+ + +``` -Luego de guardar y actualizar la página `http://127.0.0.1:8000` obviamente verás un error `NoReverseMatch` familiar, ¿verdad? +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? ## URL -Abrimos `blog/urls.py` y añadimos una línea: +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} ```python - url(r'^post/new/$', views.post_new, name='post_new'), -``` +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: -Y el código final tendrá este aspecto: +{% filename %}blog/urls.py{% endfilename %} ```python - 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'), - ] -``` +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. -Después de actualizar el sitio, veremos un `AttributeError`, puesto que no tenemos la vista `post_new` implementada. Vamos a añadirla ahora. +## post_new view -## Vista post_new +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: -Es el momento de abrir el archivo `blog/views.py` y agregar las siguientes líneas al resto de las filas `from`: +{% filename %}blog/views.py{% endfilename %} ```python - from .forms import PostForm -``` +from .forms import PostForm +``` + +And then our *view*: -y nuestra *vista*: +{% filename %}blog/views.py{% endfilename %} ```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}) +``` -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. +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. -## Plantilla +## Template -Tenemos que crear un archivo `post_edit.html` en el directorio `blog/templates/blog`. Para hacer que un formulario funcione necesitamos varias cosas: +We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: -* tenemos que mostrar el formulario. Podemos hacerlo, por ejemplo, con un simple `{% raw %}{{ form.as_p }}{% endraw %}`. -* 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. +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `
...
`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: -![CSFR Forbidden page][1] +![CSFR Forbidden page](images/csrf2.png) - [1]: images/csrf2.png +OK, so let's see how the HTML in `post_edit.html` should look: -Bueno, vamos a ver cómo quedará el HTML en `post_edit.html`: +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} ```html - {% extends 'blog/base.html' %} - - {% block content %} -

New post

- {% csrf_token %} - {{ form.as_p }} - -
- {% endblock %} -``` +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+
{% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` -¡Es hora de actualizar! ¡Si! ¡Tu formulario se muestra! +Time to refresh! Yay! Your form is displayed! -![Nuevo formulario][2] +![New form](images/new_form2.png) - [2]: images/new_form2.png +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? -Pero, ¡un momento! Si escribes algo en los campos `títle` y `text` y tratas de guardar los cambios - ¿qué pasará? +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? -¡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? +The answer is: nothing. We need to do a little bit more work in our *view*. -La respuesta es: nada. Tenemos que trabajar un poco más en nuestra *vista*. +## Saving the form -## Guardar el formulario +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: -Abre `blog/views.py` una vez más. Actualmente, lo que tenemos en la vista `post_new` es: +{% filename %}blog/views.py{% endfilename %} ```python - def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) -``` - -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). +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -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). +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). -```python - if request.method == "POST": - [...] - else: - form = PostForm() -``` +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): -Es hora de llenar los puntos `[...]`. Si el `method` es `POST` queremos construir el `PostForm` con los datos del formulario, ¿no? Lo haremos con: +{% filename %}blog/views.py{% endfilename %} ```python - form = PostForm(request.POST) -``` +if request.method == "POST": + [...] +else: + form = PostForm() +``` -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()`. +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: -Comprobamos que el formulario es válido y, si es así, ¡lo podemos salvar! +{% filename %}blog/views.py{% endfilename %} ```python - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() -``` +form = PostForm(request.POST) +``` -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. +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. -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: +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} ```python - from django.shortcuts import redirect -``` +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` -Agrégalo al principio del archivo. Y ahora podemos decir: vé a la página `post_detail` del post recién creado. +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! -```python - return redirect('post_detail', pk=post.pk) -``` -Si este paso te da un error "NoReverseMatch", es debido a que la url no ha sido nombrada. +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} -En el archivo `blog/urls.py` Cambia lo siguiente: ```python - url(r'^post/(?P[0-9]+)/$', views.post_detail) +from django.shortcuts import redirect ``` -por + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + ```python - url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail') +return redirect('post_detail', pk=post.pk) ``` -`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. +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? -Bien, hablamos mucho, pero probablemente queremos ver como se ve ahora la *vista*, ¿verdad? +{% filename %}blog/views.py{% endfilename %} ```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}) -``` +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}) +``` -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`. +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! -Probablemente has visto que no hemos definido la fecha de publicación. Vamos a introducir un *botón publicar* en **Django Girls Tutorial: Extensions**. +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. -¡Eso es genial! +That is awesome! -## Validación de formularios +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. -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. +![Logged in error](images/post_create_error.png) -Trata de guardar el formulario sin `title` y `text`. ¡Adivina qué pasará! +## Form validation -![Validación de formularios][3] +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. - [3]: images/form_validation2.png +Try to save the form without `title` and `text`. Guess what will happen! -Django se encarga de validar que todos los campos en el formulario estén correctos. ¿No es genial? +![Form validation](images/form_validation2.png) -> 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. +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? -![Error de inicio de sesión][4] +## Edit form - [4]: images/post_create_error.png +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) -## Editar el formulario +Open `blog/templates/blog/post_detail.html` and add the line -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). +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} -Abre el archivo `blog/templates/blog/post_detail.html` y añade esta línea: +```html + +``` -```python - -``` +so that the template will look like this: -para que la plantilla quede: +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html - {% extends 'blog/base.html' %} - - {% block content %} -
+{% extends 'blog/base.html' %} + +{% block content %} +
{% if post.published_date %} - {{ post.published_date }} +
+ {{ post.published_date }} +
{% endif %} -

{{ post.title }}

{{ post.text|linebreaksbr }}

- {% endblock %} -``` +
+{% endblock %} +``` + +In `blog/urls.py` we add this line: -En el archivo `blog/urls.py` añadimos esta línea: +{% filename %}blog/urls.py{% endfilename %} ```python - url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), -``` + url(r'^post/(?P\d+)/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*. +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. -Abramos el archivo `blog/views.py` y añadamos al final esta línea: +Let's open `blog/views.py` and add this 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.save() - return redirect('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: +{% filename %}blog/views.py{% endfilename %} ```python - form = PostForm(request.POST, instance=post) -``` +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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… -como al abrir un formulario con este post para editarlo: +{% filename %}blog/views.py{% endfilename %} ```python - form = PostForm(instance=post) -``` +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} -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: +```python +form = PostForm(instance=post) +``` -![Botón editar][5] +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: - [5]: images/edit_button2.png +![Edit button](images/edit_button2.png) -Al dar click ahí, debes ver el formulario con nuestro post del blog: +When you click it you will see the form with our blog post: -![Editar formulario][6] +![Edit form](images/edit_form2.png) - [6]: images/edit_form2.png +Feel free to change the title or the text and save the changes! -¡Siéntete libre de cambiar el título o el texto y guarda los cambios! +Congratulations! Your application is getting more and more complete! -¡Felicitaciones! ¡Tu aplicación está cada vez más completa! +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ -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/ +## Security -## Una cosa más: ¡Tiempo de implementación! +Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. -Veamos si todo esto funciona en PythonAnywhere. ¡Tiempo de hacer otro despliegue! +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: -* Primero, haz un commit con tu nuevo código y súbelo a GitHub +{% filename %}blog/templates/blog/base.html{% endfilename %} +```html + ``` -$ git status -$ git add --all . -$ git status -$ git commit -m "Added views to create/edit blog post inside the site." -$ git push + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} ``` -* Luego, en una [consola Bash de PythonAnywhere][7] +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + ``` -$ cd my-first-blog -$ git pull -[...] + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} ``` -* Finalmente, ve a la pestaña [Web][8] y haz click en **Reload**. +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to Github: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + - [7]: https://www.pythonanywhere.com/consoles/ - [8]: https://www.pythonanywhere.com/web_app_setup/ +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. -¡Y eso debería ser todo! Felicidades :) +And that should be it! Congrats :) \ No newline at end of file diff --git a/es/django_installation/README.md b/es/django_installation/README.md index 51205bb952f..7834993e063 100755 --- a/es/django_installation/README.md +++ b/es/django_installation/README.md @@ -1,113 +1,7 @@ -# Instalación de Django +# Django installation -> Parte de este capitulo esta basado en los tutoriales de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. > -> 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. +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! - [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 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 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 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` en tu directorio home: - - mkdir djangogirls - cd djangogirls - - -Haremos un virtualenv llamado `myvenv`. El comando general estará en el formato: - - python3 -m venv myvenv - - -### Windows - -Para crear un nuevo `virtualenv`, debes abrir la consola (te lo indicamos unos cuantos capítulos antes, ¿recuerdas?) y ejecuta `C:\Python34\python -m venv myvenv`. Se verá así: - - C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv - - -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 y OS X - -Crear un `virtualenv` en Linux y OS X es tan simple como ejecutar `python3 -m venv myvenv`. Se verá así: - - ~/djangogirls$ python3 -m venv myvenv - - -`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:** 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, utiliza directamente el comando `virtualenv`. -> -> ~/djangogirls$ sudo apt-get install python-virtualenv -> ~/djangogirls$ virtualenv --python=python3.4 myvenv -> - -## Trabajar con virtualenv - -Este comando anterior creará un directorio llamado `myvenv` (o cualquier nombre que hayas escogido) que contiene nuestro entorno virtual (básicamente un montón de archivos y carpetas). Todo lo que queremos hacer ahora es iniciarlo ejecutando: - - C:\Users\Name\djangogirls> myvenv\Scripts\activate - - -en Windows, o: - - ~/djangogirls$ source myvenv/bin/activate - - -en OS X y Linux. - -¡Recuerda reemplazar `myvenv` con tu nombre de `virtualenv` que hayas elegido! - -> **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 aparece este mensaje en la consola: - - (myvenv) C:\Users\Name\djangogirls> - - -o: - - (myvenv) ~/djangogirls$ - - -¡Nota que el prefijo `(myvenv)` aparece! - -Cuando trabajes en un entorno virtual, `python` automáticamente se referirá a la versión correcta, de modo que puedes utilizar `python` en vez de `python3`. - -Tenemos todas las dependencias importantes en su lugar. ¡Finalmente podemos instalar Django! - -## 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: `==`). - - (myvenv) ~$ pip install django==1.8 - Downloading/unpacking django==1.8 - Installing collected packages: django - Successfully installed django - Cleaning up... - - -En Windows - -> 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-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! +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/es/django_installation/instructions.md b/es/django_installation/instructions.md new file mode 100644 index 00000000000..0bc080f7055 --- /dev/null +++ b/es/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/es/django_models/README.md b/es/django_models/README.md index 792ee596c23..7aa11d11732 100755 --- a/es/django_models/README.md +++ b/es/django_models/README.md @@ -1,39 +1,40 @@ -# Modelos en Django +# Django models -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`. +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. -## Objetos +## Objects -Hay un concepto en el mundo de la programación llamado `programación orientada a objetos`. La idea es que en lugar de escribir todo como una aburrida secuencia de instrucciones de programación podemos modelar cosas y definir cómo interactúan con las demás. +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. -Entonces ¿Qué es un objeto? Es un conjunto de propiedades y acciones. Suena raro, pero te daremos un ejemplo. +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. -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). +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). -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`). +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). - Gato - --------- - color - edad - humor - dueño - ronronear() - rasguñar() - alimentarse(comida_de_gato) + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) - ComidaDeGato - ---------- - sabor + + CatFood + -------- + taste -Básicamente se trata de describir cosas reales en el código con propiedades (llamadas `propiedades del objeto`) y las acciones (llamadas `métodos`). +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). -Y ahora, ¿cómo modelamos los posts en el blog? Queremos construir un blog, ¿no? +How will we model blog posts then? We want to build a blog, right? -Tenemos primero que responder algunas preguntas: ¿Qué es un post de un blog? ¿Qué características debe tener? +We need to answer the question: What is a blog post? What properties should it have? -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. +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. Post -------- @@ -44,131 +45,155 @@ Bueno, seguro que nuestros posts necesitan un texto con su contenido y un títul 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? +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? -Así que vamos a necesitar el método `publicar`. +So we will need a `publish` method. -Puesto que ya sabemos lo que queremos lograr, ¡podemos empezar a moderlarlo en Django! +Since we already know what we want to achieve, let's start modeling it in Django! -## Modelo en Django +## Django model -Sabiendo qué es un objeto, podemos crear un modelo en Django para nuestros posts en el blog. +Knowing what an object is, we can create a Django model for our blog post. -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. +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. -Piensa en el modelo en la base de datos como una hoja de cálculo con columnas (campos) y filas (datos). +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). -### Creando una aplicación +### Creating an application -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`): +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} (myvenv) ~/djangogirls$ python manage.py startapp blog -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: +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: djangogirls - ├── mysite - | __init__.py - | settings.py - | urls.py - | wsgi.py + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 ├── manage.py - └── blog - ├── migrations - | __init__.py + └── mysite ├── __init__.py - ├── admin.py - ├── models.py - ├── tests.py - └── views.py + ├── settings.py + ├── urls.py + └── wsgi.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: +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} ```python - INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'blog', - ) +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] ``` -### Creando el Modelo Post +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. -En el archivo `blog/models.py` definimos todos los objetos llamados `Models` - este es un lugar en el cual definiremos nuestro modelo post. +Let's open `blog/models.py`, remove everything from it, and write code like this: -Vamos abrir `blog/models.py`, quitamos todo y escribimos un código como este: +{% filename %}blog/models.py{% endfilename %} ```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 -``` +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` -> 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"). +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). -Da un poco de miedo, ¿verdad? Pero no te preocupes, ¡vamos a explicar qué significan estas líneas! +It looks scary, right? But don't worry – we will explain what these lines mean! -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 ...`. +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. -`class Post(models.Model):` - esta línea define nuestro modelo (es un `objeto`). +`class Post(models.Model):` – this line defines our model (it is an `object`). -* `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. +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. -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?). +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) -* `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. +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. -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). +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). -¿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`). +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `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. +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. -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! +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. -### Crear tablas para los modelos en tu base de datos +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! -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í: +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} (myvenv) ~/djangogirls$ python manage.py makemigrations blog Migrations for 'blog': - 0001_initial.py: + blog/migrations/0001_initial.py: + - Create model Post -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: +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} (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! 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! +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/es/django_orm/README.md b/es/django_orm/README.md index 1a572c54e64..31c47f27764 100755 --- a/es/django_orm/README.md +++ b/es/django_orm/README.md @@ -1,146 +1,218 @@ -# ORM de Django y QuerySets +# Django ORM and QuerySets -En este capítulo aprenderás cómo Django se conecta a la base de datos y almacena los datos en ella. ¡Vamos a sumergirnos! +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! -## ¿Qué es un QuerySet? +## What is a QuerySet? -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. +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. -Es más fácil de aprender con ejemplos. Vamos a intentarlo, ¿de acuerdo? +It's easiest to learn by example. Let's try this, shall we? ## Django shell -Abre la consola y escribe este comando: +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} (myvenv) ~/djangogirls$ python manage.py shell -El resultado debería ser: +The effect should be like this: - (InteractiveConsole) - >>> - +{% filename %}command-line{% endfilename %} -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. +```python +(InteractiveConsole) +>>> +``` -### Ver todos los objetos +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. -Vamos a mostrar todos nuestros posts primero. Puedes hacerlo con el siguiente comando: +### All objects - >>> Post.objects.all() - Traceback (most recent call last): - File "", line 1, in - NameError: name 'Post' is not defined - +Let's try to display all of our posts first. You can do that with the following command: -¡Uy! Apareció un error. Nos dice que no hay ningún objeto Post. Esto es correcto, ¡nos olvidamos de importarlo primero! +{% filename %}command-line{% endfilename %} - >>> from blog.models import Post - +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` -Esto es simple: importamos el modelo `Post` de `blog.models`. Vamos a intentar mostrar todos los posts nuevamente: +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! - >>> Post.objects.all() - , ]> - +{% filename %}command-line{% endfilename %} -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? +```python +>>> from blog.models import Post +``` -### Crear objetos +We import the model `Post` from `blog.models`. Let's try displaying all posts again: -Esta es la forma de crear un nuevo objeto Post en la base de datos: +{% filename %}command-line{% endfilename %} - >>> Post.objects.create(author=me, title='Sample title', text='Test') - +```python +>>> Post.objects.all() +, ]> +``` -Pero hay un ingrediente faltante: `me`. Necesitamos pasar una instancia del modelo `User` como autor. ¿Cómo hacemos eso? +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? -Primero importemos el modelo User: +### Create object - >>> from django.contrib.auth.models import User - +This is how you create a new Post object in database: -¿Qué usuarios tenemos en nuestra base de datos? Veamos: +{% filename %}command-line{% endfilename %} - >>> User.objects.all() - ]> - +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` -Este es el super usuario que creamos anteriormente, Vamos a obtener una instancia de ese usuario ahora: +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? - me = User.objects.get(username='ola') - +Let's import User model first: -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. +{% filename %}command-line{% endfilename %} -Ahora finalmente podemos crear nuestro primer post: +```python +>>> from django.contrib.auth.models import User +``` - >>> Post.objects.create(author=me, title='Sample title', text='Test') - +What users do we have in our database? Try this: -¡Hurra! ¿Quieres probar si funcionó? +{% filename %}command-line{% endfilename %} - >>> Post.objects.all() - , , ]> - +```python +>>> User.objects.all() +]> +``` -### Agrega más posts +This is the superuser we created earlier! Let's get an instance of the user now: -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. +{% filename %}command-line{% endfilename %} -### Filtrar objetos +```python +>>> me = User.objects.get(username='ola') +``` -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: +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. - >>> Post.objects.filter(author=me) - , , , ]> - +Now we can finally create our post: -¿O tal vez querramos ver todos los posts que contengan la palabra 'title' en el campo `title`? +{% filename %}command-line{% endfilename %} - >>> Post.objects.filter(title__contains='title') - , ]> - +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` -> **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". +Hurray! Wanna check if it worked? -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: +{% filename %}command-line{% endfilename %} - >>> from django.utils import timezone - >>> Post.objects.filter(published_date__lte=timezone.now()) - [] +```python +>>> Post.objects.all() +, , ]> +``` -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: +There it is, one more post in the list! - >>> post = Post.objects.get(id=1) - +### Add more posts -¡Luego utiliza el método `publish` para publicarlo! +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. - >>> post.publish() - +### Filter objects -Ahora intenta obtener la lista de posts publicados nuevamente (presiona la tecla con la flecha hacia arriba 3 veces y presiona Enter): +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: - >>> Post.objects.filter(published_date__lte=timezone.now()) - ]> - +{% filename %}command-line{% endfilename %} -### Ordenando objetos +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` -Los QuerySets también te permiten ordenar la lista de objetos. Intentemos ordenarlos por el campo `created_date`: +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? - >>> Post.objects.order_by('created_date') - , , , ]> - +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} -También podemos invertir el ordenamiento agregando `-` al principio: +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` - >>> Post.objects.order_by('-created_date') - , , , ]> +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Chaining QuerySets + +You can also combine QuerySets by **chaining** them together: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') -¡Genial! ¡Ahora estás lista para la siguiente parte! Para cerrar la consola, tipea: +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} - >>> exit() - $ +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/es/django_templates/README.md b/es/django_templates/README.md index 868b94dc88a..263eb1fd835 100755 --- a/es/django_templates/README.md +++ b/es/django_templates/README.md @@ -1,106 +1,106 @@ -# Plantillas de Django +# Django templates -¡Es hora de mostrar algunos datos! Django nos provee las útiles **template tags** para ello. +Time to display some data! Django gives us some helpful built-in **template tags** for that. -## ¿Qué son las template tags? +## What are 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. +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. -**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. +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! -## Mostrar la plantilla post list +## Display post list template -En el capítulo anterior dimos a nuestra plantilla una lista de posts en la variable `posts`. Ahora lo mostraremos en HTML. +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. -Para imprimir una variable en una plantilla de Django, utilizamos llaves dobles con el nombre de la variable dentro, así: +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: -``` html - {{ posts }} -``` +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -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: +```html +{{ posts }} +``` -![Figura 13.1][1] +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: - [1]: images/step1.png +![Figure 13.1](images/step1.png) -Como puedes ver, todo lo que obtenemos es esto: +As you can see, all we've got is this: - , ]> - +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` -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: +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: -``` html - {% for post in posts %} - {{ post }} - {% endfor %} -``` +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -Prueba esto en tu plantilla. +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. -![Figura 13.2][2] +![Figure 13.2](images/step2.png) - [2]: images/step2.png +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: -¡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í: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -``` html +```html + + +{% for post in posts %}
-

Django Girls Blog

+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

- - {% 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: +{% endfor %} +``` -![Figura 13.3][3] +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} - [3]: images/step3.png +![Figure 13.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 `|linebreaksbr` está dirigiendo el texto de los posts a través de un filtro para convertir saltos de línea en párrafos. +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. -## Una cosa más +## One more thing -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... +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… -* Primero, sube tu código a GitHub +* First, push your code to Github -``` -$ git status -[...] -$ git add --all . -$ git status -[...] -$ git commit -m "Modified templates to display posts from database." -[...] -$ git push -``` +{% filename %}command-line{% endfilename %} -* Luego, identifícate en [PythonAnywhere][4] y ve a tu **consola Bash** (o empieza una nueva), y ejecuta: + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + -``` -$ cd my-first-blog -$ git pull -[...] -``` +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: -* Finalmente, ve a la [pestaña Web][5] y presiona **Reload** en tu aplicación web. ¡Tu actualización debería poder verse! +{% filename %}PythonAnywhere command-line{% endfilename %} - [4]: https://www.pythonanywhere.com/consoles/ - [5]: https://www.pythonanywhere.com/web_app_setup/ + $ cd my-first-blog + $ git pull + [...] + -¡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. +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. -¿Funciona como un encanto? ¡Estamos orgullosos! Aléjate de tu computadora por un rato, te has ganado un descanso. :) +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. -![Figura 13.4][6] +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) - [6]: images/donut.png +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/es/django_urls/README.md b/es/django_urls/README.md index 3ced93e3a42..c491b27de5c 100755 --- a/es/django_urls/README.md +++ b/es/django_urls/README.md @@ -1,123 +1,129 @@ -# Django urls +# 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. +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. -## ¿Qué es una URL? +## What is a 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): +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) -![URL][1] +![Url](images/url.png) - [1]: images/url.png +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. -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. +## How do URLs work in Django? -## ¿Cómo funcionan las URLs en Django? +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: -Vamos a abrir el archivo `mysite/urls.py` y ver cómo es: +{% filename %}mysite/urls.py{% endfilename %} -``` 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)), - ] -``` +```python +"""mysite URL Configuration -Como puedes ver, Django ya puso algo aquí para nosotros. +[...] +""" +from django.conf.urls import url +from django.contrib import admin -Las líneas que comienzan con `#` son comentarios - significa que esas líneas no serán ejecutadas por Python. Muy útil, ¿verdad? +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. -Ya está aquí la URL de admin, que visitaste en el capítulo anterior: +The admin URL, which you visited in previous chapter, is already here: -``` python - url(r'^admin/', include(admin.site.urls)), -``` +{% filename %}mysite/urls.py{% endfilename %} -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. +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. ## Regex -¿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. +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. -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: +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: - ^ 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 - +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern -Cualquier otra cosa en la definición del URL será tomada literalmente. +Anything else in the URL definition will be taken literally. -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. +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. -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í: +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: -* **^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 +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern -## ¡Tu primer URL de Django! +## Your first Django URL! -¡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. +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. -También queremos mantener el archivo `mysite/urls.py` limpio, así que importaremos URLs de nuestro `blog` al archivo `mysite/urls.py` principal. +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. -Elimina las líneas comentadas (líneas comenzando con `#`) y agrega una línea que importará `blog.urls` en el url principal (`''`). +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. -Tu archivo `mysite/urls.py` debería verse como este: +Your `mysite/urls.py` file should now look like this: -``` 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')), - ] -``` +{% filename %}mysite/urls.py{% endfilename %} -Django ahora redirigirá todo lo que vaya hacia 'http://127.0.0.1:8000/' a `blog.urls` y buscará más instrucciones allí. +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin -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. +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. ## blog.urls -Crea un nuevo archivo vacío `blog/urls.py`. ¡Muy bien! Agrega estas primeras dos líneas: +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} -``` python - from django.conf.urls import include, url - from . import views +```python +from django.conf.urls import 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) +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) -Luego de esto, podemos agregar nuestro primer patrón URL: +After that, we can add our first URL pattern: -``` python - urlpatterns = [ - url(r'^$', views.post_list), - ] -``` +{% filename %}blog/urls.py{% endfilename %} -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/'. +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` -¿Todo bien? Abre http://127.0.0.1:8000/ en tu navegador para ver el resultado. +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. -![Error][2] +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. - [2]: images/error1.png +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. -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: +![Error](images/error1.png) -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. +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. -> Si quieres saber más sobre Django URLconfs, mira la documentación oficial: https://docs.djangoproject.com/en/1.8/topics/http/urls/ +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/es/django_views/README.md b/es/django_views/README.md index e62bd13fb42..07afe091a52 100755 --- a/es/django_views/README.md +++ b/es/django_views/README.md @@ -1,38 +1,44 @@ -# Vistas de Django - ¡Es hora de crear! +# Django views – time to create! -Es hora de deshacerse del error que hemos creado en el capítulo anterior :) +Time to get rid of the bug we created in the last chapter! :) -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**. +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. -Las Vistas se colocan en el archivo `views.py`. Agregaremos nuestras *views* al archivo `blog/views.py`. +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. ## blog/views.py -Bien, vamos abrir este archivo y ver lo que contiene: +OK, let's open up this file and see what's in there: -``` python - from django.shortcuts import render - - # Create your views here. +{% filename %}blog/views.py{% endfilename %} + +```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: +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. -``` python - def post_list(request): - return render(request, 'blog/post_list.html', {}) -``` +Let's create a *view* as the comment suggests. Add the following minimal view below it: -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`. +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` -Guarda el archivo, dirígete a http://127.0.0.1:8000/ y veamos lo que tenemos ahora. +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. -¡Otro error! Leamos lo que está pasando ahora: +Save the file, go to http://127.0.0.1:8000/ and see what we've got. -![Error][1] +Another error! Read what's going on now: - [1]: images/error.png +![Error](images/error.png) -Este es uno fácil: *TemplateDoesNotExist*. ¡Vamos a arreglar este error creando una plantilla en el siguiente capítulo! +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! -> Aprende más acerca de las views de Django leyendo la documentación oficial: https://docs.djangoproject.com/en/1.8/topics/http/views/ +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/es/dynamic_data_in_templates/README.md b/es/dynamic_data_in_templates/README.md index f991de7c0b5..807bb666ebc 100755 --- a/es/dynamic_data_in_templates/README.md +++ b/es/dynamic_data_in_templates/README.md @@ -1,72 +1,81 @@ -# Datos dinámicos en las plantillas +# Dynamic data in templates -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? +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? -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. +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. -Muy bien, ahora ¿cómo lo hacemos? +OK, so how will we achieve this? -Necesitamos abrir nuestro archivo `blog/views.py`. Hasta ahora la *view* `post_list` se ve así: +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} ```python - from django.shortcuts import render - - def post_list(request): - return render(request, 'blog/post_list.html', {}) +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 línea `from .models import Post` de la siguiente forma: +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} ```python - from django.shortcuts import render - from .models import Post +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`). +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). -¿Pero ahora qué sigue? Para tomar publicaciones reales del modelo `Post`, necesitamos algo llamado `QuerySet` (conjunto de consultas). +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. ## QuerySet -Ya debes estar familiarizada con la forma en que funcionan los QuerySets. Hablamos de ellos en el capítulo [Django ORM (QuerySets)][1]. +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). - [1]: ../django_orm/README.md +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! -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! +{% filename %}blog/views.py{% endfilename %} - Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') - +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` -Ahora pondremos este bloque de código en el archivo `blog/views.py`, agregándolo a la función `def post_list(request)`: +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} ```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', {}) +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', {}) ``` -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. +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. -La última parte es pasar el QuerySet `posts` a la plantilla (veremos cómo mostrarla en el siguiente capítulo). +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. -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 `''`. +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. -Finalmente nuestro archivo `blog/views.py` debería verse así: +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} ```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}) +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}) ``` -¡Terminamos! Ahora regresemos a nuestra plantilla y mostremos este QuerySet. +That's it! Time to go back to our template and display this QuerySet! -Si quieres leer un poco más acerca de QuerySets en Django, puedes darle un vistazo a: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/es/extend_your_application/README.md b/es/extend_your_application/README.md index 8c0d2bae5b3..0bae760be7c 100755 --- a/es/extend_your_application/README.md +++ b/es/extend_your_application/README.md @@ -1,16 +1,17 @@ -# Amplía tu aplicación +# Extend your application -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. +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. -¡Hora de practicar! +Time to practice! -Lo primero que necesitamos en nuestro blog es, obviamente, una página para mostrar un post, ¿cierto? +The first thing we need in our blog is, obviously, a page to display one post, right? -Ya tenemos un modelo `Post`, así que no necesitamos añadir nada a `models.py`. +We already have a `Post` model, so we don't need to add anything to `models.py`. -## Crea un enlace en la plantilla +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} -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' %} @@ -27,90 +28,97 @@ Vamos a empezar añadiendo un enlace dentro del archivo `blog/templates/blog/pos {% endblock %} ``` -Queremos tener un enlace a una página de detalle sobre el título del post. Vamos a cambiar `

{{ post.title }}

` dentro del enlace: -``` +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html

{{ post.title }}

``` -Es hora de explicar el misterioso `{% url '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 %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail -`post_detail` es el nombre de la *view* que queremos crear. +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! -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í: +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: -![NoReverseMatch error][1] +![NoReverseMatch error](images/no_reverse_match2.png) - [1]: images/no_reverse_match2.png +## Create a URL to a post's detail -¡Vamos a crear una URL en `urls.py` para nuestro *view* `post_detail`! +Let's create a URL in `urls.py` for our `post_detail` *view*! -### URL: http://127.0.0.1:8000/post/1/ +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ -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: +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} ```python from django.conf.urls import url from . import views urlpatterns = [ - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), ] ``` -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"! +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: -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*. +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! -`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]+)`. +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. -¡Bien! ¡Actualiza la página: http://127.0.0.1:8000/ ¡Boom! ¡Sin embargo vemos otro error! Como era de esperarse. +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! -![AttributeError][2] +![AttributeError](images/attribute_error2.png) - [2]: images/attribute_error2.png +Do you remember what the next step is? Of course: adding a view! -¿Te acuerdas del próximo paso? Por supuesto: ¡agregar una view! +## Add a post's detail view -## post_detail view +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an 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! +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: -Ahora, queremos sólo un post del blog. Para ello podemos usar querysets como este: +{% filename %}blog/views.py{% endfilename %} ```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. +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! -![DoesNotExist error][3] +![DoesNotExist error](images/does_not_exist2.png) - [3]: images/does_not_exist2.png +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. -¡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](images/404_2.png) -![Page not found][4] +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. - [4]: images/404_2.png +OK, time to add a *view* to our `views.py` file! -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. +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. -¡Es hora de agregar una *view* a nuestro archivo `views.py`! +We should open `blog/views.py` and add the following code near the other `from` lines: -Deberíamos abrir `blog/views.py` y agregar el siguiente código: +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render, get_object_or_404 ``` -Cerca de otras líneas `from`. Y en el final del archivo añadimos nuestra *view*: +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} ```python def post_detail(request, pk): @@ -118,74 +126,72 @@ def post_detail(request, pk): return render(request, 'blog/post_detail.html', {'post': post}) ``` -Sí. Es hora de actualizar la página: http://127.0.0.1:8000/ +Yes. It is time to refresh the page: http://127.0.0.1:8000/ -![Post list view][5] +![Post list view](images/post_list2.png) - [5]: images/post_list2.png +It worked! But what happens when you click a link in blog post title? -¡Funcionó! Pero ¿qué pasa cuando haces click en un enlace en el título del post? +![TemplateDoesNotExist error](images/template_does_not_exist2.png) -![TemplateDoesNotExist error][6] +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! - [6]: images/template_does_not_exist2.png +## Create a template for the post details -¡Oh no! ¡Otro error! Pero ya sabemos cómo lidiar con eso, ¿no? ¡Tenemos que añadir una plantilla! +We will create a file in `blog/templates/blog` called `post_detail.html`. -Crearemos un archivo en `blog/templates/blog` llamado `post_detail.html`. +It will look like this: -Se verá así: +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html {% extends 'blog/base.html' %} {% block content %} -    
-        {% if post.published_date %} -            
-                {{ post.published_date }} -            
-        {% endif %} -        

{{ post.title }}

-        

{{ post.text|linebreaksbr }}

-    
+
+ {% 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? +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? -`{% 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. +{% 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 %} -Bien, podemos actualizar nuestra página y ver si `Page Not Found` se ha ido. +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. -![Post detail page][7] +![Post detail page](images/post_detail2.png) - [7]: images/post_detail2.png +Yay! It works! -¡Yay! ¡Funciona! +## One more thing: deploy time! -## Una cosa más: ¡Tiempo de implementación! +It'd be good to see if your website will still be working on PythonAnywhere, right? Let's try deploying again. -Sería bueno verificar que tu sitio web aún funcionará en PythonAnywhere, ¿cierto? Intentemos desplegar de nuevo. +{% filename %}command-line{% endfilename %} -``` -$ git status -$ git add --all . -$ git status -$ git commit -m "Added views to create/edit blog post inside the site." -$ git push -``` + $ 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 + -* Luego, en una [consola Bash de PythonAnywhere][8] +Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): -``` -$ cd my-first-blog -$ git pull [...] -``` +{% filename %}command-line{% endfilename %} -* Finalmente, ve a la pestaña [Web][9] y haz click en **Reload**. + $ cd my-first-blog + $ git pull + [...] + - [8]: https://www.pythonanywhere.com/consoles/ - [9]: https://www.pythonanywhere.com/web_app_setup/ +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. -¡Y eso debería ser todo! Felicidades :) +And that should be it! Congrats :) \ No newline at end of file diff --git a/es/how_the_internet_works/README.md b/es/how_the_internet_works/README.md index 8a5e936cb93..efd95c3f4b2 100755 --- a/es/how_the_internet_works/README.md +++ b/es/how_the_internet_works/README.md @@ -1,55 +1,47 @@ -# ¿Cómo funciona Internet? +# How the Internet works -> Este capitulo está inspirado por la charla "How the Internet works" de 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. +> +> This chapter is inspired by the talk "How the Internet works" by Jessica McKellar (http://web.mit.edu/jesstess/www/). -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'? +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`? -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. +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. -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. +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, follow its instructions, and present these files that your website is made of, exactly the way you want. -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. +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. -Ok, quizás te preguntes cómo luce Internet, ¿cierto? +OK, but you want to know how the Internet looks, right? -¡Te hemos hecho una imagen! Luce algo así: +We drew you a picture! It looks like this: -![Figura 1.1][1] +![Figure 1.1](images/internet_1.png) - [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: -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: +![Figure 1.2](images/internet_3.png) - [2]: http://submarinecablemap.com/ +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. -![Figura 1.2][3] +It looks like this: - [3]: images/internet_3.png +![Figure 1.3](images/internet_2.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. +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!" -Se parece a esto: +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. -![Figura 1.3][4] +![Figure 1.4](images/internet_4.png) - [4]: images/internet_2.png +That's how it works - 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! -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!" +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. -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. +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). -![Figura 1.4][5] +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). - [5]: images/internet_4.png +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. :) -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 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 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 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 personalizadas, especialmente para la persona que acaba de escribir, ¿cierto? Django nos ayuda con la creación de estas cartas personalizadas :). - -Basta de charlas, ¡pongamos manos a la obra! +Enough talk – time to create! \ No newline at end of file diff --git a/es/html/README.md b/es/html/README.md index acfc1e723ae..004985089c2 100755 --- a/es/html/README.md +++ b/es/html/README.md @@ -1,210 +1,213 @@ -# Introducción a HTML +# Introduction to HTML -Te estarás preguntando, ¿qué es una plantilla? +What's a template, you may ask? -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. +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. -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**). +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**). -## ¿Qué es HTML? +## What is HTML? -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 is a code that is interpreted by your web browser – such as Chrome, Firefox or Safari – to display a web page for the user. -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**. +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**. -## ¡Tu primera plantilla! +## Your first template! -Crear una plantilla significa crear un archivo de plantilla. Todo es un archivo, ¿verdad? Probablemente hayas notado esto ya. +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. -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: +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 -(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.) +(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.) -Y ahora crea un archivo `post_list.html` (déjalo en blanco por ahora) dentro de la carpeta `blog/templates/blog`. +And now create a `post_list.html` file (just leave it blank for now) inside the `blog/templates/blog` directory. -Mira cómo se ve su sitio web ahora: http://127.0.0.1:8000/ +See how your website looks now: 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`. +> 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 keys together) and start it again by running a `python manage.py runserver` command. -![Figura 11.1][1] +![Figure 11.1](images/step1.png) - [1]: images/step1.png +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. -¡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. +Add the following to your template file: -Añade lo siguiente a tu archivo de plantilla: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -``` html - -

Hi there!

-

It works!

- +```html + +

Hi there!

+

It works!

+ ``` -¿Cómo luce ahora tu sitio web? Haz click para ver: http://127.0.0.1:8000/ +So how does your website look now? Visit it to find out: http://127.0.0.1:8000/ -![Figura 11.2][2] +![Figure 11.2](images/step3.png) - [2]: images/step3.png +It worked! Nice work there :) -¡Funcionó! Buen trabajo :) +* 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 -* 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 +## Head and body -## Cabeza & cuerpo +Each HTML page is also divided into two elements: **head** and **body**. -Cada página HTML también se divide en dos elementos: **head** y **body**. +* **head** is an element that contains information about the document that is not displayed on the screen. -* **head** es un elemento que contiene información sobre el documento que no se muestra en la pantalla. +* **body** is an element that contains everything else that is displayed as part of the web page. -* **body** es un elemento que contiene todo lo que se muestra como parte de la página web. +We use `` to tell the browser about the configuration of the page, and `` to tell it what's actually on the page. -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. +For example, you can put a web page title element inside the ``, like this: -Por ejemplo, puedes ponerle un título a la página web dentro de la ``, así: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -``` html - - - Ola's blog - - -

Hi there!

-

It works!

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

Hi there!

+

It works!

+ + ``` -Guarda el archivo y actualiza tu página. +Save the file and refresh your page. -![Figura 11.3][3] +![Figure 11.3](images/step4.png) - [3]: images/step4.png +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). -¿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). +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). -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). +It's like putting things into boxes. You have one big box, ``; inside it there is ``, and that contains still smaller boxes: `

`. -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: `

`. +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. -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. +## Customize your template -## Personaliza tu plantilla +You can now have a little fun and try to customize your template! Here are a few useful tags for that: -¡Ahora puedes divertirte un poco y tratar de personalizar tu plantilla! Aquí hay algunas etiquetas útiles para eso: +* `

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 paragraph of text

` +* `text` emphasizes your text +* `text` strongly emphasizes your text +* `
` goes to another line (you can't put anything inside br and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page -* `

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 +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: -Aquí hay un ejemplo de una plantilla completa: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -``` 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.

-
- - +```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.

+
+ + ``` -Aquí hemos creado tres secciones `div`. +We've created three `div` sections here. -* 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. +* 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. -Nos da este efecto: +It gives us this effect: -![Figura 11.4][4] +![Figure 11.4](images/step6.png) - [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! 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**. +What we really want to do is display real posts added in our Django admin – and that's where we're going next. -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. +## One more thing: deploy! -## Una cosa más: ¡despliega! +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: -Sería bueno ver todo esto disponible en Internet, ¿no? Hagamos otro despliegue en PythonAnywhere: +### Commit, and push your code up to Github -### Haz un commit y sube tu código a GitHub +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): -En primer lugar, veamos qué archivos han cambiado desde que hicimos el despliegue por última vez: +{% filename %}command-line{% endfilename %} $ 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: +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes within this directory: + +{% filename %}command-line{% endfilename %} $ git add --all . -> **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. +> **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): -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): +{% filename %}command-line{% endfilename %} $ git status -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. +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 "Cambie el HTML para la página." +{% filename %}command-line{% endfilename %} + + $ git commit -m "Changed the HTML for the site." -> **Nota** Asegúrate de usar comillas dobles alrededor del mensaje de commit. +> **Note** Make sure you use double quotes around the commit message. + +Once we've done that, we upload (push) our changes up to GitHub: -Una vez que hicimos esto, subimos (push) nuestros cambios a PythonAnywhere: +{% filename %}command-line{% endfilename %} - git push + $ git push -### Descarga tu nuevo código a PythonAnywhere y actualiza tu aplicación web +### Pull your new code down to PythonAnywhere, and reload your web app -* 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 -[...] -``` +* Open up the [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one). Then, run: - [5]: https://www.pythonanywhere.com/consoles/ +{% filename %}command-line{% endfilename %} -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. + $ cd ~/my-first-blog + $ git pull + [...] + -* Finalmente, dirígete a la pestaña [Web][6] y selecciona **Reload** en tu aplicación web. +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. - [6]: https://www.pythonanywhere.com/web_app_setup/ +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. -¡Tu actualización debería estar en línea! Actualiza tu sitio web en el navegador. Ahora deberías poder ver tus cambios :) +Your update should be live! Go ahead and refresh your website in the browser. Changes should be visible. :) \ No newline at end of file diff --git a/es/installation/README.md b/es/installation/README.md new file mode 100644 index 00000000000..a7c627136c8 --- /dev/null +++ b/es/installation/README.md @@ -0,0 +1,58 @@ +# 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 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. \ No newline at end of file diff --git a/es/intro_to_command_line/README.md b/es/intro_to_command_line/README.md index de1565f63c0..5fb6d48dd1f 100755 --- a/es/intro_to_command_line/README.md +++ b/es/intro_to_command_line/README.md @@ -1,97 +1,154 @@ -# Introducción a la interfaz de línea de comandos +# Introduction to the command-line interface -Es emocionante, ¿verdad? Vas a escribir tu primera línea de código en pocos minutos :) +> For readers at home: this chapter is covered in the [Your new friend: Command Line](https://www.youtube.com/watch?v=jvZLWhkzX-8) video. -**Permítenos presentarte a tu primer nuevo amigo: ¡la línea de comandos!** +It's exciting, right?! You'll write your first line of code in just a few minutes! :) -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. +**Let us introduce you to your first new friend: the command line!** -## ¿Qué es la línea de comandos? +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. -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*. +> **Note** Please note that throughout this book we use the terms 'directory' and 'folder' interchangeably but they are one and the same thing. -## Abrir la interfaz de línea de comandos +## What is the command line? -Lo primero que debemos hacer para empezar a experimentar con nuestra interfaz de linea de comandos es abrirla. +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*. -### Windows +## Open the command-line interface -Ir al menú Inicio → Todos los programas → Accesorios → Command Prompt +To start some experiments we need to open our command-line interface first. -### Mac OS X + -Aplicaciones → Servicios → Terminal +Go to Start menu → Windows System → Command Prompt. -### Linux +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. -Está probablemente en Aplicaciones → Accesorios → Terminal, pero eso depende de tu distribución. Si no lo encuentras, Googlealo :) + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, but that may depend on your system. If it's not there, just Google it. :) + + ## Prompt -Ahora deberías ver una ventana blanca o negra que está esperando tus órdenes. +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: -Si estás en Mac o Linux, probablemente verás `$`, así: +{% filename %}command-line{% endfilename %} $ -En Windows, es un signo así `>`, como este: + + + + +On Windows, it's a `>` sign, like this: + +{% filename %}command-line{% endfilename %} > -Cada comando será precedido por este signo y un espacio, pero no tienes que escribirlo. Tu computadora lo hará por ti :) + + +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 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. -> 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. +## Your first command (YAY!) -## Tu primer comando (¡YAY!) +Let's start by typing this command: -Vamos a empezar con algo simple. Escribe este comando: + + +{% filename %}command-line{% endfilename %} $ whoami -o + + + + +{% filename %}command-line{% endfilename %} > whoami -Y luego oprime la tecla Enter. Este es el resultado: + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} - $ whoami olasitarska + $ whoami + olasitarska -Como puedes ver, la computadora sólo te presentó tu nombre de usuario. Bien, ¿eh? :) +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! + +## Basics -> Trata de escribir cada comando, no copies y pegues. ¡Te acordarás más de esta manera! +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? -## Básicos +### Current directory -Cada sistema operativo tiene un conjunto diferente de comandos para la línea de comandos, así que asegúrate de seguir las instrucciones para tu sistema operativo. Vamos a intentarlo, ¿de acuerdo? +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: -### Directorio actual + -Sería bueno saber dónde estamos ahora, ¿cierto? Vamos a ver. Escribe este comando y oprime Enter: +{% filename %}command-line{% endfilename %} $ pwd /Users/olasitarska -Si estás en Windows: +> Note: 'pwd' stands for 'print working directory'. + + + + - > cd +{% filename %}command-line{% endfilename %} + + > 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. +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + -> Nota: 'pwd' significa 'print working directory' - en español, 'mostrar directorio de trabajo'. +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. * * * -### Lista de archivos y directorios +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: -¿Qué hay aquí? Sería bueno saber. Veamos: + + +{% filename %}command-line{% endfilename %} $ ls Applications @@ -101,175 +158,272 @@ Probablemente verás algo similar en tu máquina. Una vez que abres la línea de ... -Windows: + + + + +{% 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 + 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 ... +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + * * * -### Cambia el directorio actual +### Change current directory + +Now, let's go to our Desktop directory: -¿Quizás podemos ir a nuestro escritorio? + + +{% filename %}command-line{% endfilename %} $ cd Desktop -Windows: + + + + +{% filename %}command-line{% endfilename %} > cd Desktop -Comprueba si realmente ha cambiado: + + +Check if it's really changed: + + - $ pwd +{% filename %}command-line{% endfilename %} + + $ pwd /Users/olasitarska/Desktop -Windows: + - > cd + + +{% filename %}command-line{% endfilename %} + + > cd C:\Users\olasitarska\Desktop -¡Aquí está! + + +Here it is! -> 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. +> 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` key twice to get a list of options. * * * -### Crear directorio +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + -¿Qué tal si creamos un directorio de Django Girls en tu escritorio? Puedes hacerlo de esta manera: +{% filename %}command-line{% endfilename %} - $ mkdir djangogirls + $ mkdir practice -Windows: + - > mkdir djangogirls + + +{% filename %}command-line{% endfilename %} + + > mkdir practice -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 :) + + +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: 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. +> 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. * * * -### ¡Ejercicios! +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: -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: +{% filename %}command-line{% endfilename %} - $ cd djangogirls + $ cd practice $ mkdir test $ ls + test -Windows: + - > cd djangogirls + + +{% filename %}command-line{% endfilename %} + + > cd practice > mkdir test - > dir - 08/05/2014 19:28 < DIR > test + > dir + 05/08/2014 07:28 PM test -¡Felicitaciones! :) + + +Congrats! :) * * * -### Limpiar +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. -No queremos dejar un desorden, así que vamos a eliminar todo lo que hicimos hasta este momento. +First, we need to get back to Desktop: -En primer lugar, tenemos que volver al escritorio: + + +{% filename %}command-line{% endfilename %} $ cd .. -Windows: + + + + +{% filename %}command-line{% endfilename %} > cd .. -`cd` `..` cambiará el directorio actual al directorio padre (que significa el directorio que contiene el directorio actual). + + +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: -Revisa dónde estás: + - $ pwd +{% filename %}command-line{% endfilename %} + + $ pwd /Users/olasitarska/Desktop -Windows: + + + - > cd +{% filename %}command-line{% endfilename %} + + > cd C:\Users\olasitarska\Desktop -Ahora es hora de eliminar el directorio `djangogirls`. + + +Now time to delete the `practice` directory: -> **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. +> **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. - $ rm -r djangogirls + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice -Windows: + + + - > rmdir/s djangogirls - djangogirls, ¿Estás seguro ? Y +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y -Hecho! Asegurémonos que en verdad fueron borrados, vamos a ver: + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} $ ls -Windows: + + + + +{% filename %}command-line{% endfilename %} > dir -### Salida + + +### Exit -¡Esto es todo por ahora! Ahora puedes cerrar la línea de comandos sin problemas. Vamos a hacerlo al estilo hacker, ¿bien? :) +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 -Windows: + + + + +{% filename %}command-line{% endfilename %} > exit -Genial, ¿no? :) + -## Índice +Cool, huh? :) -Aquí hay una lista de algunos comandos útiles: +## Summary -| 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** | +Here is a summary of some useful commands: -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. +| Command (Windows) | Command (Mac OS / Linux) | Description | Example | +| ----------------- | ------------------------ | -------------------------- | ------------------------------------------------- | +| exit | exit | close the window | **exit** | +| cd | cd | change directory | **cd test** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | -Si tienes curiosidad, [ss64.com][1] contiene una referencia completa de comandos para todos los sistemas operativos. +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. - [1]: http://ss64.com +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. -## ¿Lista? +## Ready? -¡Vamos a sumergirnos en Python! +Let's dive into Python! \ No newline at end of file diff --git a/es/python_installation/README.md b/es/python_installation/README.md index ba64077782c..93f81cb42d9 100755 --- a/es/python_installation/README.md +++ b/es/python_installation/README.md @@ -1,72 +1,15 @@ -# Vamos a empezar con Python +# Let’s start with Python -¡Por fin estamos aquí! +We're finally here! -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. +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 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! +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 simpler than other programming languages, but don't worry – Python is also really powerful! -# Instalación de Python +# Python installation -> Este subcapítulo se basa en un tutorial de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots/) +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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! -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-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 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 Python instalado o si quieres una versión diferente, puedes instalarlo como sigue: - -#### Ubuntu - -Tipea este comando en tu consola: - - sudo apt-get install python3.4 - - -#### Fedora - -Usa este comando en tu consola: - - sudo dnf install python3.4 - - -#### openSUSE - -Usa este comando en tu consola: - - sudo zypper install python3 - - -### OS X - -Debes ir al sitio web https://www.python.org/downloads/release/python-342/ y descargar el instalador de Python: - -* 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 fue exitosa abriendo la *Terminal* y ejecutando el comando `python3`: - - $ python3 --version - Python 3.4.2 - - -* * * - -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. +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/es/python_installation/instructions.md b/es/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/es/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/es/python_introduction/README.md b/es/python_introduction/README.md index 97c6e1cd0e6..c1642302532 100755 --- a/es/python_introduction/README.md +++ b/es/python_introduction/README.md @@ -1,509 +1,710 @@ -# Introducción a Python +# Introduction to Python -> Parte de este capítulo se basa en tutoriales por Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). -¡Vamos a escribir algo de código! +Let's write some code! ## Python prompt -Para empezar a jugar con Python, tenemos que abrir una *línea de comandos* en nuestra computadora. Ya sabes cómo hacerlo, lo aprendiste en el capítulo de [Introducción a la línea de comandos][1]. +> 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. - [1]: /intro_to_command_line/README.html +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. -Una vez que estés lista, sigue las siguientes instrucciones. +Once you're ready, follow the instructions below. -Queremos abrir una consola de Python, así que escribe `python3` y pulsa Enter. +We want to open up a Python console, so type in `python` on Windows or `python3` on Mac OS/Linux and hit `enter`. + +{% filename %}command-line{% endfilename %} $ python3 - Python 3.4.2 (...) - Type "copyright", "credits" or "license" for more information. + Python 3.6.1 (...) + Type "help", "copyright", "credits" or "license" for more information. >>> -## ¡Tu primer comando en Python! +## Your first Python command! -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. +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. -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 `>>>`. +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. -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. +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. - >>> 2 + 3 - 5 - +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` -¡Bien! ¿Ves como salió la respuesta? ¡Python sabe matemáticas! Podrías intentar otros comandos como: +Nice! See how the answer popped out? Python knows math! You could try other commands like: - `4 * 5` - `5 - 1` - `40 / 2` -Diviértete con esto por un momento y luego vuelve aquí :). +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +Have fun with this for a little while and then get back here. :) -Como puedes ver, Python es una gran calculadora. Si te estás preguntando qué más puede hacer... +As you can see, Python is a great calculator. If you're wondering what else you can do… ## Strings -¿Y tu nombre? Escribe tu nombre de pila en frases como ésta: +How about your name? Type your first name in quotes like this: - >>> "Ola" - 'Ola' - +{% filename %}command-line{% endfilename %} -¡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. +```python +>>> "Ola" +'Ola' +``` -Las cadenas pueden ser concatenadas. Prueba esto: +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. - >>> "Hola " + "Ola" - 'Hola Ola' - +Strings can be strung together. Try this: -También puedes multiplicar las cadenas con un número: +{% filename %}command-line{% endfilename %} - >>> "Ola" * 3 - 'OlaOlaOla' - +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` -Si necesitas poner un apóstrofe dentro de tu cadena, tienes dos maneras de hacerlo. +You can also multiply strings with a number: -Usando comillas dobles: +{% filename %}command-line{% endfilename %} - >>> "Runnin' down the hill" - "Runnin' down the hill" - +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` -o escapando el apóstrofe con una barra invertida (`\`): +If you need to put an apostrophe inside your string, you have two ways to do it. - >>> 'Runnin\' down the hill' - "Runnin' down the hill" - +Using double quotes: -Bien, ¿eh? Para ver tu nombre en letras mayúsculas, simplemente escribe: +{% filename %}command-line{% endfilename %} - >>> "Ola".upper() - 'OLA' - +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` -¡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. +or escaping the apostrophe with a backslash (``): -Si quisieras saber el número de letras que contiene tu nombre, también existe una función para esto. +{% filename %}command-line{% endfilename %} - >>> len("Ola") - 3 - +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` -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`. +Nice, huh? To see your name in uppercase letters, simply type: -### Resumen +{% filename %}command-line{% endfilename %} -Ok, suficiente sobre las cadenas. Hasta ahora has aprendido sobre: +```python +>>> "Ola".upper() +'OLA' +``` -* **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 *, combina valores para producir uno nuevo -* **funciones** - como upper() y len(), realizan opciones sobre los objetos. +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. -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! +If you want to know the number of letters contained in your name, there is a **function** for that too! -## Errores +{% filename %}command-line{% endfilename %} -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: +```python +>>> len("Ola") +3 +``` - >>> len(304023) - Traceback (most recent call last): - File "", line 1, in - TypeError: object of type 'int' has no len() - +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. -¡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? +### Summary - >>> len(str(304023)) - 6 - +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! -¡Funcionó! Utilizamos la función `str` dentro de la función `len`. `str()` convierte todo a strings. +## Errors -* La función `str` convierte cosas en **strings** -* La función `int` convierte cosas en **integers** +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`: -> Importante: podemos convertir números en texto, pero no podemos necesariamente convertir texto en números - ¿qué sería `int('hello')`? +{% 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? + +{% 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? ## Variables -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. +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. -Supongamos que queremos crear una nueva variable llamada `name`: +Let's say we want to create a new variable called `name`: - >>> name = "Ola" - +{% filename %}command-line{% endfilename %} -¿Ves? ¡Es fácil! Es simplemente: name equivale a Ola. +```python +>>> name = "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: +We type name equals Ola. - >>> name - '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`: -¡Súper! Tu primer variable :). Siempre podrás cambiar a lo que se refiere: +{% filename %}command-line{% endfilename %} - >>> name = "Sonja" - >>> name - 'Sonja' - +```python +>>> name +'Ola' +``` -Puedes usarla dentro de funciones también: +Yippee! Your first variable! :) You can always change what it refers to: - >>> len(name) - 5 - +{% filename %}command-line{% endfilename %} -Increíble, ¿verdad? Por supuesto, las variables pueden ser cualquier cosa, ¡también números! Prueba esto: +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` - >>> a = 4 - >>> b = 6 - >>> a * b - 24 - +You can use it in functions too: -Pero ¿qué pasa si usamos el nombre equivocado? ¿Puedes adivinar qué pasaría? ¡Vamos a probar! +{% filename %}command-line{% endfilename %} - >>> city = "Tokyo" - >>> ctiy - Traceback (most recent call last): -   File "", line 1, in - NameError: name 'ctiy' is not defined - +```python +>>> len(name) +5 +``` -¡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. +Awesome, right? Of course, variables can be anything – numbers too! Try this: -Juega con esto por un rato y mira que puedes hacer! +{% filename %}command-line{% endfilename %} -## La función print +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` -Intenta esto: +But what if we used the wrong name? Can you guess what would happen? Let's try! - >>> name = 'Maria' - >>> name - 'Maria' - >>> print(name) - Maria - +{% filename %}command-line{% endfilename %} -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. +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` -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. +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. -## Listas +Play with this for a while and see what you can do! -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 :) +## The print function -Anímate y crea una lista: +Try this: - >>> [] - [] - +{% filename %}command-line{% endfilename %} -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: +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` - >>> lottery = [3, 42, 12, 19, 30, 59] - +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. -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! +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. - >>> len(lottery) - 6 - +## Lists -¡Sí! `len()` puede darte el número de objetos en una lista. Útil, ¿verdad? Tal vez la ordenemos ahora: +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. :) - >>> lottery.sort() - +Go ahead and create a list: -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ó: +{% filename %}command-line{% endfilename %} - >>> print(lottery) - [3, 12, 19, 30, 42, 59] - +```python +>>> [] +[] +``` -Como puedes ver, los números en tu lista ahora están ordenados de menor a mayor. ¡Felicidades! +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: -¿Te gustaría invertir ese orden? ¡Vamos a hacerlo! +{% filename %}command-line{% endfilename %} - >>> lottery.reverse() - >>> print(lottery) - [59, 42, 30, 19, 12, 3] - +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` -Fácil, ¿no? Si quieres añadir algo a tu lista, puedes hacerlo escribiendo este comando: +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! - >>> lottery.append(199) - >>> print(lottery) - [59, 42, 30, 19, 12, 3, 199] - +{% filename %}command-line{% endfilename %} -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: +```python +>>> len(lottery) +6 +``` - >>> print(lottery[0]) - 59 - >>> print(lottery[1]) - 42 - +Yes! `len()` can give you a number of objects in a list. Handy, right? Maybe we will sort it now: -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. +{% filename %}command-line{% endfilename %} -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? +```python +>>> lottery.sort() +``` -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 +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: -## Diccionarios +{% filename %}command-line{% endfilename %} -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: +```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! -Esto demuestra que acabas de crear un diccionario vacío. ¡Hurra! +Maybe we want to reverse that order? Let's do that! -Ahora, trata escribiendo el siguiente comando (intenta reemplazando con propia información): +{% filename %}command-line{% endfilename %} - >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} - +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` -Con este comando, acabas de crear una variable `participant` con tres pares clave-valor: +If you want to add something to your list, you can do this by typing this command: -* 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 ella). +{% filename %}command-line{% endfilename %} -Puedes verificar el contenido de claves individuales con esta sintaxis: +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` - >>> print(participant['name']) - Ola - +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: -Lo ves, es similar a una lista. Pero no necesitas recordar el índice - sólo el nombre. +{% filename %}command-line{% endfilename %} -¿Qué pasa si le pedimos a Python el valor de una clave que no existe? ¿Puedes adivinar? ¡Pruébalo y verás! +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` - >>> participant['age'] - Traceback (most recent call last): - File "", line 1, in - KeyError: 'age' - +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 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. + +{% filename %}command-line{% endfilename %} -¡Mira, otro error! Este es un **KeyError**. Python te ayuda y te dice que la llave `'age'` no existe en este diccionario. +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` -¿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. +That worked like a charm! -* ¿Sólo necesitas una secuencia ordenada de elementos? Usa una lista. -* ¿Necesitas asociar valores con claves, así puedes buscarlos eficientemente (usando las claves) más adelante? Utiliza un diccionario. +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? -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: +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html - >>> participant['favorite_language'] = 'Python' - +## Dictionaries -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: +> For readers at home: this part is covered in the [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c) video. - >>> len(participant) - 4 - +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: -Espero tenga sentido hasta ahora. :) ¿Lista para más diversión con los diccionarios? Salta a la siguiente línea para algunas cosas sorprendentes. +{% filename %}command-line{% endfilename %} -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: +```python +>>> {} +{} +``` - >>> participant.pop('favorite_numbers') - >>> participant - {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} - +This shows that you just created an empty dictionary. Hurray! -Como puedes ver en la salida, el par de clave-valor correspondiente a la clave 'favorite_numbers' ha sido eliminado. +Now, try writing the following command (try substituting your own information, too): -Además de esto, también puedes cambiar un valor asociado a una clave ya creada en el diccionario. Teclea: +{% filename %}command-line{% endfilename %} - >>> participant['country'] = 'Germany' - >>> participant - {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} - +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` -Como puedes ver, el valor de la clave `'country'` ha sido modificado de `'Poland'` a `'Germany'`. :) ¿Emocionante? ¡Hurra! Has aprendido otra cosa asombrosa. +With this command, you just created a variable named `participant` with three key–value pairs: -### Resumen +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). -¡Genial! Sabes mucho sobre programación ahora. En esta última parte aprendiste sobre: +You can check the content of individual keys with this syntax: -* **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 +{% filename %}command-line{% endfilename %} -¿Emocionada por la siguiente parte? :) +```python +>>> print(participant['name']) +Ola +``` -## Compara cosas +See, it's similar to a list. But you don't need to remember the index – just the name. -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: +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! - >>> 5 > 2 - True - >>> 3 < 1 - False - >>> 5 > 2 * 2 - True - >>> 1 == 1 - True - >>> 5 != 2 - True - +{% filename %}command-line{% endfilename %} -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? +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` -¿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. +Look, another error! This one is a **KeyError**. Python is helpful and tells you that the key `'age'` doesn't exist in this dictionary. -Da dos tareas más a Python: +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. - >>> 6 >= 12 / 2 - True - >>> 3 <= 2 - False - +- 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. -`>` y `<` son fáciles, pero ¿qué es significa `> =` y `< =`? Se leen así: +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: -* x `>` y significa: x es mayor que y -* x `<` y significa: x es menor que y -* x `<=` y significa: x es menor o igual que y -* x `>=` y significa: x es mayor o igual que y +{% filename %}command-line{% endfilename %} -¡Genial! ¿Quieres hacer uno mas? Intenta esto: +```python +>>> participant['favorite_language'] = 'Python' +``` - >>> 6 > 2 and 2 < 3 - True - >>> 3 > 2 and 2 < 1 - False - >>> 3 > 2 or 2 < 1 - True - +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: -Puedes darle a Python todos los números para comparar que quieras, y siempre te dará una respuesta. Muy inteligente, ¿verdad? +{% filename %}command-line{% endfilename %} -* **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 +```python +>>> len(participant) +4 +``` -¿Has oído la expresión "comparar peras con manzanas"? Vamos a probar el equivalente en Python: +I hope it makes sense up to now. :) Ready for some more fun with dictionaries? Read on for some amazing things. - >>> 1 > 'django' - Traceback (most recent call last): - File "", line 1, in - TypeError: unorderable types: int() > str() - +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +``` -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. +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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 -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. +Incidentally, you just learned about a new type of object in Python. It's called **Boolean**. -Hay sólo dos objetos Boolean: - True - False +There are only two Boolean objects: -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.) +- True +- False -Los valores booleanos pueden ser variables, también. Ve el siguiente ejemplo: +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well, of course.) - >>> a = True - >>> a - True - +Booleans can be variables, too! See here: -También puedes hacerlo de esta manera: +{% filename %}command-line{% endfilename %} - >>> a = 2 > 5 - >>> a - False - +```python +>>> a = True +>>> a +True +``` -Practica y diviértete con los booleanos ejecutando los siguientes comandos: +You can also do it this way: -* `True and True` -* `False and True` -* `True or 1 == 1` -* `1 != 2` +{% filename %}command-line{% endfilename %} -¡Felicidades! Los booleanos son una de las funciones más geniales en programación y acabas de aprender cómo usarlos. +```python +>>> a = 2 > 5 +>>> a +False +``` -# ¡Guárdalo! +Practice and have fun with Booleans by trying to run the following commands: -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: +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` -* 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 -* ¡Ejecutarlo! +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! -Para salir del intérprete de Python que hemos estado usando, simplemente escribe la función exit(): +# Save it! - >>> exit() - $ - +> 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. -Esto te llevará de vuelta a la línea de comandos. +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: -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: +- Exit the Python interpreter +- Open up our code editor of choice +- Save some code into a new python file +- Run it! - [2]: ../code_editor/README.md +To exit from the Python interpreter that we've been using, simply type the `exit()` function -``` python - print('Hello, Django girls!') +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ ``` -> **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 :) +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!') +``` + +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. -Obviamente, ahora eres una desarrolladora Python muy experimentada, así que siéntete libre de escribir algo del código que has aprendido hoy. +> **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. :) -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. +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. -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 una Mac, el comando se verá algo como esto: +On a Mac, the command will look something like this: - cd ~/Desktop +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop -En Linux, va a ser así (la palabra "Desktop" puede estar traducida a tu idioma): + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): - cd ~/Desktop +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop -Y en Windows, será así: + + + - cd %HomePath%\Desktop +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop -Si te quedas atascada, sólo pide ayuda. + + + -y luego usa Python para ejecutar el código en el archivo como sigue: +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +Now use Python to execute the code in the file like this: + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Hello, Django girls! -¡Muy bien! Ejecutaste tu primer programa de Python desde un archivo. ¿No se siente increíble? +Note: on Windows 'python3' is not recognized as a command. Instead, use 'python' to execute the file: + +{% filename %}command-line{% endfilename %} + +```python +> python python_intro.py +``` -Ahora puedes moverte a una herramienta esencial en la programación: +Alright! You just ran your first Python program that was saved to a file. Feel awesome? -## If...elif...else +You can now move on to an essential tool in programming: -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**. +## If … elif … else -Reemplaza el código en tu archivo **python_intro.py** por esto: +Lots of things in code should be executed only when given conditions are met. That's why Python has something called **if statements**. -``` python - if 3 > 2: +Replace the code in your **python_intro.py** file with this: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: ``` -Si lo guardáramos y lo ejecutáramos, veríamos un error como este: +If we were to save and run this, we'd see an error like this: + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py File "python_intro.py", line 2 @@ -511,115 +712,194 @@ Si lo guardáramos y lo ejecutáramos, veríamos un error como este: 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 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!') +```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. +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. -Guárdalo y ejecútalo de nuevo: +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. -### ¿Qué pasa si la condición no es verdadera? +### What if a condition isn't True? -En ejemplos anteriores, el código fue ejecutado sólo cuando las condiciones eran ciertas. Pero Python también tiene declaraciones `elif` y `else`: +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') - else: - print('5 is not greater than 2') +if 5 > 2: + print('5 is indeed greater than 2') +else: + print('5 is not greater than 2') ``` -Al ejecutar esto se imprimirá: +When this is run it will print out: + +{% filename %}command-line{% endfilename %} $ 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`: +If 2 were a greater number than 5, then the second command would be executed. Let's see how `elif` works: -``` python - name = 'Sonja' - if name == 'Ola': - print('Hey Ola!') - elif name == 'Sonja': - print('Hey Sonja!') - else: - print('Hey anonymous!') +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') ``` -y al ejecutarlo: +and executed: + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Hey Sonja! -¿Ves lo que pasó ahí? +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 %} -### Resumen +```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! :(") +``` -En los últimos tres ejercicios aprendiste acerca de: +Python runs through each test in sequence and prints: -* **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** - 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 +{% filename %}command-line{% endfilename %} -¡Es hora de leer la última parte de este capítulo! + $ python3 python_intro.py + Perfect, I can hear all the details + -## ¡Tus propias funciones! +## Comments -¿Recuerdas las funciones como `len()` que puedes ejecutar en Python? Bien, buenas noticias, ¡ahora aprenderás cómo escribir tus propias funciones! +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. -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: +Let's see how that looks: -``` python - def hi(): - print('Hi there!') - print('How are you?') - - hi() +{% 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!") ``` -Bien, ¡nuestra primera función está lista! +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. + +### Summary + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +Remember functions like `len()` that you can execute in Python? Well, good news – you will learn how to write your own functions now! -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. +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 give it a go. Replace the code in **python_intro.py** with the following: -Ejecutemos esto y veamos qué sucede: +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} $ 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: +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. -``` python - def hi(name): +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): ``` -Como puedes ver, ahora dimos a nuestra función un parámetro que llamamos `name`: +As you can see, we now gave our function a parameter that we called `name`: -``` python - def hi(name): - if name == 'Ola': - print('Hi Ola!') - elif name == 'Sonja': - print('Hi Sonja!') - else: - print('Hi anonymous!') - - hi() -``` +{% filename %}python_intro.py{% endfilename %} -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: +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Traceback (most recent call last): @@ -628,87 +908,111 @@ Como puedes notar, tuvimos que poner dos indentaciones antes de la función `pri 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: +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: -``` python - hi("Ola") +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Ola") ``` -y lo ejecutamos otra vez: +And run it again: + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Hi Ola! -¿Y si cambiamos el nombre? +And if we change the name? + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Sonja") +``` -``` python - hi("Sonja") -``` +And run it: -y lo corremos: +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Hi Sonja! -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: +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: + +{% filename %}command-line{% endfilename %} Hi anonymous! -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! +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! -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? +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? -``` python - def hi(name): - print('Hi ' + name + '!') - - hi("Rachel") -``` +{% filename %}python_intro.py{% endfilename %} -Ahora vamos a llamar al código: +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Hi Rachel! -¡Felicidades! Acabas de aprender cómo escribir funciones :) +Congratulations! You just learned how to write functions! :) + +## Loops -## Bucles +> For readers at home: this part is covered in the [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) video. -Esta ya es la última parte. ¿Eso fue rápido, verdad? :) +This is the last part already. That was quick, right? :) -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. +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. -¿Todavía recuerdas las listas? Hagamos una lista de las chicas: +Still remember lists? Let's do a list of girls: -``` python - girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] -``` +{% filename %}python_intro.py{% endfilename %} -Queremos saludar a todas ellas por su nombre. Tenemos la función `hi` que hace eso, así que vamos a usarla en un bucle: +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` -``` python - for name in girls: -``` +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: -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. +{% filename %}python_intro.py{% endfilename %} -Aquí está el código completo que estará en el archivo: +```python +for name in girls: +``` -``` python - def hi(name): - print('Hi ' + name + '!') - - girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] - for name in girls: - hi(name) - print('Next girl') -``` +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') -y cuando lo ejecutamos: +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Hi Rachel! @@ -723,15 +1027,20 @@ y cuando lo ejecutamos: 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`. +As you can see, everything you put inside a `for` statement with an indent will be repeated for every element of the list `girls`. -También puedes usar el `for` en números usando la función `range`: +You can also use `for` on numbers using the `range` function: - for i in range(1, 6): - print(i) - +{% filename %}python_intro.py{% endfilename %} -Lo que imprimirá: +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% filename %}command-line{% endfilename %} 1 2 @@ -740,16 +1049,14 @@ Lo que imprimirá: 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 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). +`range` is a function that creates a list of numbers following one after the other (these numbers are provided by you as parameters). -## Resumen +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. -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í! +## Summary -Tal vez quieras hacer algo distinto por un momento - estirarte, caminar un poco, descansar tus ojos - antes de pasar al siguiente capítulo. :) +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! -![Cupcake][3] +You might want to briefly do something else – stretch, walk around for a bit, rest your eyes – before going on to the next chapter. :) - [3]: images/cupcake.png +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/es/template_extending/README.md b/es/template_extending/README.md index 390be1c98e6..35997f913d3 100755 --- a/es/template_extending/README.md +++ b/es/template_extending/README.md @@ -1,14 +1,14 @@ -# Extendiendo Plantillas +# Template extending -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. +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. -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. +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! -## Creando una plantilla base +## Create a base template -Una plantilla base es la plantilla más básica que extiendes en cada página de tu sitio web. +A base template is the most basic template that you extend on every page of your website. -Vamos a crear un archivo `base.html` en `blog/templates/blog/`: +Let's create a `base.html` file in `blog/templates/blog/`: blog └───templates @@ -17,72 +17,99 @@ Vamos a crear un archivo `base.html` en `blog/templates/blog/`: post_list.html -Luego ábrelo y copia todo lo que hay en `post_list.html` al archivo `base.html`, de la siguiente manera: +Then open it up and copy everything from `post_list.html` to `base.html` file, like this: -```html - {% 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: +{% filename %}blog/templates/blog/base.html{% endfilename %} -``` html +```html +{% load staticfiles %} + + + Django Girls blog + + + + + +
- {% block content %} - {% endblock %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %}
+ ``` -Básicamente remplazamos todo entre `{% for post in posts %}{% endfor %}` con: +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} -``` html - {% block content %} - {% endblock %} +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ ``` -¿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. +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} -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: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -``` html +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} {% for post in posts %}
@@ -92,31 +119,29 @@ Ahora guárdalo y abre tu archivo `blog/templates/blog/post_list.html` de nuevo.

{{ post.text|linebreaksbr }}

{% endfor %} +{% endblock %} ``` -Y ahora agrega esta línea al inicio del archivo: -``` - {% extends 'blog/base.html' %} -``` +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: -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 %}`. Como esto: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} -``` html - {% extends 'blog/base.html' %} - - {% block content %} - {% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaksbr }}

+```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }}
- {% endfor %} - {% endblock %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} ``` -¡Eso es todo! Verifica que tu sitio web aún funcione apropiadamente :) +That's it! Check if your website is still working properly. :) -> 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`. +> 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. \ No newline at end of file diff --git a/es/whats_next/README.md b/es/whats_next/README.md index df5bd765d55..fbb1d2a7d6e 100755 --- a/es/whats_next/README.md +++ b/es/whats_next/README.md @@ -1,40 +1,25 @@ -# ¿Qué sigue? +# What's next? -¡Date muchas felicitaciones! **¡Eres increíble!**. ¡Estamos orgullosos! <3 +Congratulate yourself! **You're totally awesome**. We're proud! <3 -### ¿Qué hacer ahora? +### What to do now? -Toma un descanso y relájate. Acabas de hacer algo realmente grande. +Take a break and relax. You have just done something really huge. -Después de eso, asegúrate de: +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. -* Seguir a Django Girls en [Facebook][1] o [Twitter][2] para estar al día +### Can you recommend any further resources? - [1]: http://facebook.com/djangogirls - [2]: https://twitter.com/djangogirls +Yes! First, go ahead and try our other book, called [Django Girls Tutorial: Extensions](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). -### ¿Me puedes recomendar recursos adicionales? +Later on, you can try the resources listed below. They're all very recommended! -¡Sí! En primer lugar, sigue adelante y prueba nuestro libro llamado [Django Girls Tutorial: Extensiones][3]. - - [3]: https://tutorial-extensions.djangogirls.org - -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] - - [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://www.gettingstartedwithdjango.com/ - [11]: https://twoscoopspress.org/products/two-scoops-of-django-1-6 +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/fa-IR/GLOSSARY.md b/fa-IR/GLOSSARY.md new file mode 100644 index 00000000000..c65a983e6a3 --- /dev/null +++ b/fa-IR/GLOSSARY.md @@ -0,0 +1,3 @@ +# ویرایشگر کد + +ویرایشگر کد یک برنامه کاربردی است که به شما امکان می دهد کد خود را ذخیره کنید تا بتوانید بعدا به آن بازگردید. شما می توانید در [بخش ویرایشگر کد](./code_editor/README.md) یاد بگیرید که چطور یکی از آن‌ها را دانلود کنید \ No newline at end of file diff --git a/fa-IR/README.md b/fa-IR/README.md new file mode 100644 index 00000000000..4c69142bfbc --- /dev/null +++ b/fa-IR/README.md @@ -0,0 +1,51 @@ +# جنگو برای دختران + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> این کار تحت مجوز Creative Commons Attribution-Share Alike 4.0 مجاز است. برای مشاهده یک نسخه از این مجوز، بهhttps://creativecommons.org/licenses/by-sa/4.0/ مراجعه کنید + +## خوش آمدید + +به دوره آموزشی دختران جنگو خوش آمدید! خوشحال هستیم که شما را اینحا می‌بینیم. :) در این آموزش، شما را به سفری به پشت صحنه تکنولوژی‌های وب خواهیم برد و نگاهی اجمالی می‌اندازیم به تمام بخش‌های بزرگ و کوچکی که کنار هم قرار می‌گیرند تا وب، آن طور که می‌شناسیمش، کار کند. + +مثل تمام کارهای ناشناخته دیگر، این کار نیز یک ماجراجویی خواهد بود. اما نگران نباشید، چرا که شهامت اینجا بودن را داشته‌اید، همه چیز خوب پیش خواهد رفت. :) + +## معرفی + +آیا تا به حال احساس کرده اید دنیا هر روز بیشتر و بیشتر پیرامون تکنولوژی می‌گذرد که شما (هنوز) با آن ارتباط برقرار نمی‌کنید؟ آیا شده به ساختن یک وبسایت فکر کنید ولی انگیزه کافی را برای شروع اش نداشته باشید؟ آیا تا به حال به این فکر کرده‌اید که دنیای نرم‌افزار برای آنکه شما وارد آن بشوید، بیش از حد پیچیده است؟ + +ما خبرهای خوبی برای شما داریم. برنامه نویسی آن قدر که به نظر می‌رسد سخت نیست و می‌خواهیم نشان دهیم که حتی میتواند جالب هم باشد. + +این آموزش شما را به طرز جادویی تبدیل به برنامه نویس نخواهد کرد. اگر بخواهید برنامه نویس خوبی شوید، باید ماه‌ها و یا حتی سال‌ها برایش وقت بگذارید. ولی ما می‌خواهیم نشان دهیم که برنامه نویسی یا ساختن وبسایت آنقدرها که به نظر می‌رسد پیچیده نیست. سعی ما این است که قدم به قدم و جز به جز جلو برویم، تا زیاد گیج نشوید. + +امیدواریم بتوانیم کاری کنیم که شما هم به اندازه ما از تکنولوژی خوشتان بیاید! + +## در این آموزش چه چیزی یاد خواهید گرفت؟ + +وقتی این برنامه آموزشی را تمام کنید، یک برنامه وب که کار می‌کند یعنی وبلاگ خودتان را خواهید داشت. به شما نشان خواهیم داد چه طور آن را روی اینترنت بگذارید تا بقیه کارتان را ببینند! + +کمابیش شبیه این خواهد شد: + +![تصویر 0.1](images/application.png) + +> اگر خودتان به تنهایی با این آموزش کار می‌کنید و مربی ندارید تا به شما کمک کند، در صورت بروز هر مشکلی ما یک سیستم چت برای شما داریم: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). ما از مربی‌ها و شرکت کنندگان قبلی خود خواسته ایم تا هر چند وقت یکبار اینجا باشند و به بقیه کمک کنند! از پرسیدن سوال هایتان نترسید! + +خوب،[ بیایید از ابتدا شروع کنیم... ](./how_the_internet_works/README.md) + +## دنبال کردن آموزش در منزل + +فوق‌العاده خواهد بود که در یکی از کارگاه‌های دختران جنگو شرکت کنید، اما می‌دانیم که امکان شرکت همیشه فراهم نیست. به همین دلیل است که شما را تشویق می کنیم که در خانه از این آموزش استفاده کنید. برای خوانندگان در منزل، ما در حال تهیه ویدئوهایی هستیم که دنبال کردن آموزش به تنهایی را آسان‌‌تر می‌سازد. هنوز کامل نشده‌است، اما چیزهای بیشتر و بیشتری به زودی در کانال یوتیوب [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) قرار خواهد گرفت. + +در هر فصل که قبلاً پوشش داده شده است، یک لینک وجود دارد که به ویدیو صحیح اشاره می‌کند. + +## مشارکت در توسعه + +این آموزش توسط [DjangoGirls](https://djangogirls.org/) نگهداری می‌شود. در صورتی که مشکلی در این آموزش می‌بینید یا می‌خواهید آن را بروز رسانی کنید [لطفاً دستورالعمل‌های مرتبط را انجام دهید](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## آیا می‌خواهید به ما در ترجمه این دوره به زبان‌های دیگر، کمک کنید؟ + +در حال حاضر، ترجمه بر روی بستر crowdin.com نگهداری می‌شود: + +https://crowdin.com/project/django-girls-tutorial + +اگر زبان شما در [crowdin](https://crowdin.com/) لیست نشده است، [یک issue جدید](https://github.com/DjangoGirls/tutorial/issues/new) باز کنید و در مورد این زبان به ما اطلاع دهید تا ما بتوانیم آن را اضافه کنیم. \ No newline at end of file diff --git a/fa-IR/SUMMARY.md b/fa-IR/SUMMARY.md new file mode 100644 index 00000000000..4ff90958204 --- /dev/null +++ b/fa-IR/SUMMARY.md @@ -0,0 +1,35 @@ +# چکیده + +* [معرفی](README.md) +* [نصب و راه‌اندازی](installation/README.md) + * [ترمینال](installation/README.md#command-line) + * [پایتون](installation/README.md#python) + * [ویرایشگر کد](installation/README.md#code-editor) + * [محیط مجازی](installation/README.md#virtualenv) + * [جنگو](installation/README.md#django) + * [گیت](installation/README.md#git) + * [گیت هاب](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [نصب و راه اندازی (کروم بوک)](chromebook_setup/README.md) +* [اینترنت چگونه کار می‌کند](how_the_internet_works/README.md) +* [آشنایی با خط فرمان](intro_to_command_line/README.md) +* [نصب و راه اندازی پایتون](python_installation/README.md) +* [ویرایشگر کد](code_editor/README.md) +* [آشنایی با پایتون](python_introduction/README.md) +* [جنگو چیست?](django/README.md) +* [نصب و راه اندازی جنگو](django_installation/README.md) +* [اولین پروژه جنگو شما!](django_start_project/README.md) +* [مدل در جنگو](django_models/README.md) +* [پنل مدیریت در جنگو](django_admin/README.md) +* [فاز دیپلوی!](deploy/README.md) +* [URL ها در جنگو](django_urls/README.md) +* [ساخت view در جنگو!](django_views/README.md) +* [آشنایی با HTML](html/README.md) +* [ORM در جنگو](django_orm/README.md) +* [داده های پویا در templates](dynamic_data_in_templates/README.md) +* [templates در جنگو](django_templates/README.md) +* [CSS - آن را زیبا کنید](css/README.md) +* [توسعه template](template_extending/README.md) +* [برنامه خود را توسعه دهید](extend_your_application/README.md) +* [فرم در جنگو](django_forms/README.md) +* [گام بعدی چیست؟](whats_next/README.md) \ No newline at end of file diff --git a/fa-IR/chromebook_setup/README.md b/fa-IR/chromebook_setup/README.md new file mode 100644 index 00000000000..73d2075a168 --- /dev/null +++ b/fa-IR/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# نصب Chromebook + +> **نکته** اگر الان در حال گذراندن [مراحل نصب](../installation/README.md) هستید، لازم نیست مجددا این مراحل را انجام دهید و می‌توانید مستقیماً به بخش [آشنایی با پایتون](../python_introduction/README.md) بروید. + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/fa-IR/chromebook_setup/instructions.md b/fa-IR/chromebook_setup/instructions.md new file mode 100644 index 00000000000..ca0ad1132c4 --- /dev/null +++ b/fa-IR/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +اگر از Chromebook استفاده نمی‌کنید می‌توانید [از این بخش ](http://tutorial.djangogirls.org/en/installation/#install-python) عبور کنید. اگر از آن استفاده می‌کنید تجربه نصب شما کمی متفاوت خواهد بود. شما می توانید بقیه دستورالعمل نصب را نادیده بگیرید. + +### IDE ابری (PaizaCloud Cloud IDE, AWS Cloud9 و Glitch.com) + +IDE ابری ابزاری است که به شما دسترسی به یک ویرایشگر کد و یک کامپیوتر در حال کار کردن روی اینترنت را می‌دهد که می‌توانید نصب، نوشتن و اجرای برنامه‌ها را در آن انجام دهید. در زمان این آموزش، IDE ابری به عنوان * دستگاه محلی شما * عمل خواهد کرد. شما همچنان مانند سایر همکلاسی‌ها که از OS X، اوبونتو یا ویندوز استفاده می‌کنند، دستورات را در ترمینال اجرا خواهید کرد اما ترمینال شما به کامپیوتری که IDE ابری برای شما آماده کرده متصل است. در اینحا دستورالعمل استفاده از IDE های ابری ( PaizaCloud Cloud IDE، AWS Cloud9 و Glitch.com) را خواهید دید. شما می‌توانید یکی از IDE های ابری را انتخاب کنید و دستورالعمل را دنبال کنید. + +#### IDE ابری PiazaCloud + +1. به [PaizaCloud Cloud IDE](https://paiza.cloud/) بروید +2. یک حساب کاربری بسازید +3. بر روی *New Server* کلیک کنید و گزینه Django app را انتخاب کنید +4. دکمه Terminal را (در سمت چپ صفحه) بزنید + +حالا شما باید صفحه ای با یک ستون کناری و کلیدهایی در سمت چپ ببینید. بر روی دکمه "Terminal" کلیک کنید تا پنجره ترمینال با پیغامی شبیه به این باز شود: + +{% filename %}Terminal{% endfilename %} + + $ + + +ترمینال در IDE ابری PiazaCloud برای دستورات شما آماده شده است. شما می‌توانید اندازه این پنجره را تغییر دهید تا کمی بزرگتر دیده شود. + +#### AWS Cloud9 + +در حال حاضر برای استفاده از Cloud 9 باید با اکانت AWS ثبت نام کنید و مشخصات کارت اعتباری را نیز وارد کنید. + +1. Cloud 9 را از [Chrome web store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) نصب کنید +2. به [c9.io](https://c9.io) بروید و بر روی *Get started with AWS Cloud9* کلیک کنید +3. با یک حساب AWS ثبت نام کنید (به اطلاعات کارت اعتباری نیاز است اما می‌توانید به رایگان از آن استفاده کنید) +4. در داشبورد AWS عبارت *Cloud9* را در محل جستجو وارد کنید و کلید جستجو را بزنید +5. در داشبورد Cloud 9 بر روی *Create environment* کلیک کنید +6. نام آن را *django-girls* بگذارید +7. در هنگام انجام تنظیمات، در بخش "Environment Type" گزینه *Create a new instance for environment (EC2)* را و در بخش "Instance type" گزینه *t2.micro* را انتخاب کنید ("Free-tier eligible" را نشان خواهد داد). تنظیمات پیشفرض صرفه جویانه و خوب است و شما هم باقی تنظیمات پیشفرض را نگه دارید. +8. بر روی *Next step* کلیک کنید +9. بر روی *Create environment* کلیک کنید + +حالا باید صفحه‌ای با یک نوار کناری، یک صفحه اصلی بزرگ با مقداری نوشته و یک صفحه کوچک در پایین ببینید که شبیه به این خواهد بود: + +{% filename %}bash{% endfilename %} + + yourusername:~/workspace $ + + +این محدوده پایین، ترمینال شماست. شما می‌توانید از این ترمینال برای فرستادن دستورات به کامپیوتر Cloud 9 استفاده کنید. می‌توانید ابعاد این پنجره را تغییر دهید تا کمی بزرگتر دیده شود. + +#### IDE ابری Glitch.com + +1. به [Glitch.com](https://glitch.com/) بروید +2. یک حساب کاربری (https://glitch.com/signup) بسازید یا از حساب GitHub خود استفاده کنید. (راهنمای استفاده از حساب GitHubرا در زیر ببینید) +3. بر روی *New Project* کلیک کنید و گزینه *hello-webpage* را انتخاب کنید +4. بر روی گزینه کشویی Tools کلیک کنید (در سمت چپ و پایین صفحه)، سپس بر روی دکمه Terminal کلیک کنید تا یک کنسول خط فرمان باز شود: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +هنگامی که از Glitch.com به عنوان ویرایشگر ابری خود استفاده می‌کنید، لازم نیست که یک محیط مجازی بسازید، به جای آن فایل‌های زیر را باید بسازید: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +وقتی این فایل‌ها ساخته شدند، به Terminal بروید و دستورات زیر را اجرا کنید تا اولین پروژه جنگو شما ساخته شود: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +برای دیدن جزییات مربوط به پیغام خطا، می‌توانید لاگ عیب‌یابی جنگو را در اپلیکیشن Glitch فعال کنید. به سادگی کد زیر را به انتهای فایل `mysite/settings.py` اضافه کنید. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +این کار یک فایل `debug.log` می‌سازد که جزییات عملیات جنگو و پیغام‌های خطای احتمالی، در آن است، به کمک این فایل عیب‌یابی وب‌سایت بسیار ساده‌تر می‌شود. + +اولین ریستارت پروژه Glitch‌ نباید موفقیت‌آمیز باشد! (اگر بر روی منوی کشویی `Show` کلیک کنید و سپس `In a New Window` را بزنید، پیغام خطای `DisallowedHost` را دریافت خواهید کرد) در مورد این مرحله نگران نباشید، این آموزش این مشکل را به زودی و پس از به روزرسانی تنظیمات پروژه که در فایل `mysite/settings.py` است، حل خواهد کرد. + +### محیط مجازی + +یک محیط مجازی (Virtual Environment یا virtualenv) شبیه یک جعبه خصوصی است که ما می‌توانیم کدهای کامپیوتری مربوط به یک پروژه را در آن جمع کنیم. ما از آن‌ها استفاده می‌کنیم تا تکه‌های مختلف کدهای هر پروژه را جدا از پروژه دیگر نگه داریم تا بین پروژه‌ها تداخل پیش نیاید. + +اجرا: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(توجه کنید که در خط آخر ما از یک علامت مد و یک مساوی استفاده کردیم: `~=`). + +### GitHub + +یک حساب کاربری [GitHub](https://github.com) بسازید. + +### PythonAnywhere + +دوره آموزشی جنگوگرلز شامل بخشی است به نام فاز دیپلوی یا Deployment، که شامل گرفتن و انتقال دادن کدهای وبسایت شما به یک کامپیوتر در دسترس عموم (به نام سرور) است تا سایرین هم بتوانند کار شما را ببینند. + +اگر این دوره آموزشی را بر روی Chromebook که خودش کامپیوتری بر روی اینترنت است (در مقابل لپ تاپ‌های معمولی که کامپیوتری محلی محسوب می‌شوند)، انجام می‌دهید این بخش کمی عجیب خواهد بود. با این‌حال، استفاده از Cloud 9 به عنوان یک محیط کاری برای کارهای در جریان و استفاده از Python Anywhere به عنوان یک فضای معرفی و نمایش پروژه هایی که در طول زمان کامل می‌شوند، مفید است. + +بنابراین یک حساب کاربری جدید در [www.pythonanywhere.com](https://www.pythonanywhere.com) بسازید. \ No newline at end of file diff --git a/fa-IR/code_editor/README.md b/fa-IR/code_editor/README.md new file mode 100644 index 00000000000..90c36a2806f --- /dev/null +++ b/fa-IR/code_editor/README.md @@ -0,0 +1,11 @@ +# ویرایشگر کد + +> برای خوانندگان در خانه: این فصل در ویدئو [نصب پایتون و ویرایشگر کد](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) توضیح داده شده است. + +به نوشتن اولین خط کدتان نزدیک می‌شوید، زمان مناسبی برای دانلود یک ویرایشگر کد است! + +> **نکته** اگر از Chromebook استفاده میکنید، این فصل را رد کنید و مطمئن شوید که دستورالعمل [نصب Chromebook](../chromebook_setup/README.md) را دنبال کنید. IDE ابری که شما انتخاب کرده‌اید (PaizaCloud Cloud IDE یا AWS Cloud9) شامل یک ویرایشگر کد هم هست و هنگامی که یک فایل را در IDE خودتان باز می‌کنید به صورت اتوماتیک از ویرایشگر استفاده می‌کنید. +> +> **نکته** ممکن است این بخش را قبل‌تر در بخش [نصب و راه‌اندازی](../installation/README.md) انجام داده باشید، در این صورت مستقیم به بخش بعد بروید! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/fa-IR/code_editor/instructions.md b/fa-IR/code_editor/instructions.md new file mode 100644 index 00000000000..b10c0a8b471 --- /dev/null +++ b/fa-IR/code_editor/instructions.md @@ -0,0 +1,37 @@ +ویرایشگرهای مختلف زیادی وجود دارد که این امر به سلیقه شخصی برمی‌گردد. اغلب برنامه‌نویسان پایتون از محیط‌های توسعه یکپارچه (IDE, Integrated Development Environments) بسیار قدرتمند مثل PyCharm استفاده می‌کنند. اما برای یک مبتدی احتمالا خیلی مناسب نیست. پیشنهادهای ما به همان اندازه قدرتمند، اما بسیار ساده‌تر هستند. + +ما موارد زیر را پیشنهاد می‌کنیم، اما می‌توانید از مربی خود، ترجیحش را بپرسید. راحت‌تر است از مربی کمک بگیرید. + +## Visual Studio Code + +Visual Studio Code یک ویرایشگر کد است که توسط مایکروسافت توسعه داده شده و برای ویندوز، لینوکس و macOS موجود است. این ویرایشگر قابلیت عیب یابی، کنترل Git از داخل نرم افزار، برجسته سازی دستورات، سیستم هوشمند کامل کردن دستورات، سیستم snippets (جلوگیری از نوشتن بخش‌های تکراری در کدها) و بازنویسی کدها است. + +[از اینجا دانلود کنید](https://code.visualstudio.com/) + +## Gedit + +Gedit یک نرم افزار آزاد و یک ویرایشگر رایگان است که برای تمام سیستم عامل‌ها موجود است. + +[از اینجا دانلود کنید](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text یک ویرایشگر بسیار رایج است که یک دوره آزمایشی رایگان دارد و برای تمام سیستم عامل‌ها موجود است. + +[جهت دانلود کلیک نمایید](https://www.sublimetext.com/3) + +## Atom + +Atom نیز یک ویرایشگر رایج دیگر است که نرم افزاری رایگان و آزاد است و برای ویندوز، لینوکس وOS X موجود است. Atom توسط [GitHub](https://github.com/) توسعه داده شده است. + +[از اینجا دانلود کنید](https://atom.io/) + +## چرا ویرایشگر متن نصب می‌کنیم؟ + +ممکن است فکر کنید که چرا به جای استفاده از برنامه‌ای مثل Word یا Notepad، این نرم‌افزار خاص ویرایش کد را نصب می‌کنم. + +دلیل اول این است که کدها نیاز دارند که به صورت متن ساده (**plain text**) باشند و مشکل برنامه‌هایی مثل Word یا Textedit این است که متن ساده تولید نمی‌کنند، بلکه متنی غنی (با فونت و قالب‌بندی) می‌سازند و از قالب‌های سفارشی مثل [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format) استفاده می‌کنند. + +دلیل دوم این است که ویرایشگرهای متن به طور خاص برای ویرایش کد ساخته شده‌اند. بنابراین، امکاناتی مثل رنگ‌آمیزی کدها بر اساس معنایشان یا بستن خودکار نقل قول‌ها را دارند. + +همه این‌ها را بعداً در عمل خواهیم دید. به زودی، شما به ویرایشگر کد خود به عنوان یکی از ابزارهای محبوبتان نگاه خواهید کرد. :) \ No newline at end of file diff --git a/fa-IR/css/README.md b/fa-IR/css/README.md new file mode 100644 index 00000000000..074ed7e7d6f --- /dev/null +++ b/fa-IR/css/README.md @@ -0,0 +1,325 @@ +# CSS - زیبایش کن! + +بلاگ ما هنوز خیلی زشت است، نه؟ وقتش است که زیبایش کنیم. برای این کار از CSS استفاده می‌کنیم. + +## CSS چیست؟ + +CSS یا (Cascading Style Sheets) زبان مورد استفاده برای توصیف ظاهر و قالب‌بندی یک وب سایت نوشته شده در زبان نشانه گذاری، (مانند HTML) است. از آن به عنوان آرایش برای صفحه وب خود استفاده می‌کنیم. ؛) + +اما ما نمی‌خواهیم دوباره از ابتدا شروع کنیم، درست است؟ یک بار دیگر، ما از چیزی که برنامه‌نویسان در اینترنت به صورت رایگان منتشر کرده‌اند استفاده می‌کنیم. همانطور که می‌دانید اختراع دوباره چرخ جالب نیست. + +## با بوت‌ استرپ شروع کنیم! + +بوت استرپ یکی از محبوب‌ترین چارچوب‌های HTML و CSS برای توسعه وب سایت‌های زیبا است: https://getbootstrap.com/ + +توسط برنامه نویسانی که در توییتر کار می کردند نوشته شده بود. در حال حاضر توسط داوطلبانی از سراسر جهان توسعه یافته است! + +## نصب بوت استرپ + +برای نصب بوت استرپ فایل `.html` را در ویرایشگر متن باز کنید و به بخش `` خط‌های زیر را اضافه کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +این کار هیچ فایلی به پروژه شما اضافه نمی‌کند. این کد به فایلی که در اینترنت وجود دارد اشاره می‌کند. بنابراین به پیش بروید وبسایت خود را باز کنید و صفحه را ریفرش کنید. بفرمایید! + +![تصویر 14.1](images/bootstrap1.png) + +ظاهری قشنگ‌تر از قبل! + +## فایل‌های ایستا در جنگو + +در نهایت نگاهی دقیق‌تر به فایل‌هایی بیاندازیم که به آن‌ها فایل ایستا یا ثابت **static files** می‌گوییم. فایل‌های ایستا شامل تمامی فایل‌های CSS و عکس‌ها می‌باشند. محتوای آن‌ها به متن درخواست بستگی ندارد و برای هر کاربر یکسان خواهد بود. + +### فایل‌های ایستا کجای جنگو قرار میگیرند + +جنگو به هرحال می‌داند که فایل‌های ثابت در اپلیکیشن پیش ساخته "admin" کجا قرار گرفته‌اند. حالا ما لازم داریم تا چند فایل ثابت را به اپلیکیشن `blog` خودمان اضافه کنیم. + +ما این کار را با ایجاد یک پوشه به نام `static` در داخل برنامه وبلاگ انجام می‌دهیم: + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │   └── templates + └── mysite + + +جنگو به طور خودکار هر پوشه‌ای با نام "static" را در پوشه اپلیکیشن‌های شما پیدا خواهد کرد. پس از آن قادر است از محتوای آن‌ها به عنوان فایل ایستا استفاده کند. + +## اولین فایل CSS شما! + +اکنون یک فایل CSS ایجاد کنیم تا سلیقه خود را به صفحه وب تان اضافه کنیم. یک پوشه جدید با نام `css` در داخل پوشه `static` بسازید. سپس در داخل این پوشه `css`، یک فایل جدید با نام `blog.css` ایجاد کنید. آماده شد؟ + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +حالا وقت کمی CSS نوشتن است! فایل `blog/static/css/blog.css` را در ویرایشگر کد خود باز کنید. + +ما در اینجا، سفارشی سازی و یادگیری CSS را خیلی عمیق بررسی نخواهیم کرد. اگر بخواهید بیشتر در باره CSS بدانید، یک توصیه برای یک دوره رایگان، در پایین این صفحه وجود دارد. + +اما بیایید حداقل کمی به آن بپردازیم. شاید بتوانیم رنگ header هایمان را تغییر دهیم؟ برای درک رنگ‌ها، رایانه‌ها از کدهای ویژه استفاده می‌کنند. این کدها با `#` شروع می‌شوند و به ترتیب شامل 6 حرف (A-F) و اعداد (0-9) هستند. به عنان مثال، کد رنگ آبی `FF0000#` است. شما می‌توانید در آدرس http://www.colorpicker.com:/ کد رنگ بسیاری از رنگ‌ها را پیدا کنید. شما همچنین ممکن است از [رنگ‌های از پیش تعریف شده](http://www.w3schools.com/colors/colors_names.asp) از جمله `قرمز` و `سبز` استفاده کنید. + +در فایل ` blog/static/css/blog.css ` کد زیر را اضافه کنید: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1 a` انتخابگر یا selector در یک فایل CSS است. به این معنی که ما درحال تنظیم کردن فرمت هر عنصر `a` هستیم که در داخل یک بخش `h1` باشد. `h2 a` نیز دقیقا مانند همین کار را در بخش `h2` انجام می‌دهد. بنابراین وقتی ما چیزی شبیه یک `

link

` داریم، فرمت `h1 a` اعمال خواهد شد. در این مورد، ما می‌خواهیم رنگ آن را به `#C25100` تغییر دهیم که رنگ نارنجی تیره است. یا اینکه می‌توانید رنگ مورد علاقه خودتان را بگذارید فقط مطمئن باشید با رنگ سفید زمینه، کنتراست کافی داشته باشد! + +در یک فایل CSS،ما فرمت‌ بخش‌های مختلف یک فایل HTML را مشخص می‌کنیم. اولین روش شناسایی هر عنصر یا element، نام عنصر است. ممکن است این عناصر را به عنوان تگ tag از بخش HTML بخاطر داشته باشید. عناصری مانند ` a `، ` h1 `، و `body` همه نمونه‌هایی از نام یک عنصر هستند. ما همچنین عناصر را با ویژگی‌هایی مانند `class` یا `id` نیز شناسایی می‌کنیم. class و id نام‌هایی هستند که شما خودتان به عناصر مختلف نسبت می‌دهید. class ها، گروه‌های عناصر را تعریف می‌کنند و id ها به یک عنصر خاص اشاره می‌کنند. برای مثال، می‌توانید عنصر زیر را با استفاده از نام تگ، یعنی ` a`، نام کلاس ` external_link ` یا به کمک آیدی `link_to_wiki_page ` شناسایی کنید: + +```html + +``` + +شما می‌توانید در این موارد بیشتر بخوانید [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +ما همچنین باید به قالب HTML خودمان بگوییم که یک فایل CSS اضافه کرده‌ایم. فایل `blog/templates/blog/post_list.html` را در ویرایشگر کد باز کنید و خط زیر را به ابتدای آن اضافه کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +ما فقط فایل‌های ثابت یا static را در اینجا بارگیری می‌کنیم. :) بین برچسب `` و ``، پس از پیوند به فایل‌های بوت استرپ، این خط را اضافه کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +مرورگر فایل‌ها را به ترتیب می‌خواند، بنابراین ما باید مطمئن شویم که این خط در جای مناسب قرار گرفته است. در غیر این صورت کد در فایل شما ممکن است توسط کد در فایل‌های بوت استرپ لغو شود. ما فقط به قالب HTML مان می‌گوییم که فایل CSS کجا قرار دارد. + +اکنون فایل شما باید مانند این باشد: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +خب، حالا فایل را ذخیره کنید و صفحه را دوباره بارگذاری کنید! + +![تصویر 14.2](images/color2.png) + +کارت خوب بود! شاید بخواهیم کمی حاشیه سمت چپ صفحه وب مان را افزایش دهیم؟ بیایید این را امتحان کنیم! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { padding-left: 15px; } +``` + +این کد را به فایل CSS خود اضافه کنید، و ببینید چگونه کار می‌کند! + +![تصویر 14.3](images/margin2.png) + +شاید ما بتوانیم فونت را در هدر صفحه‌مان سفارشی کنیم؟ این قطعه کد را در بخش `` فایل `blog/templates/blog/post_list.html` وارد کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +همانند قبل ترتیب قرار دادن لینک‌ها را چک کنید و این خط را قبل پیوند به `blog/static/css/blog.css` قرار دهید. این خط، فونتی به نام *Lobster* را از مجموعه فونت‌های گوگل فراخوانی می‌کند (https://www.google.com/fonts). + +در فایل CSS به آدرس `blog/static/css/blog.css`، بخش تعریف عنصر ` h1 a ` را پیدا کنید (قطعه کدی که بین `{` و `}` قرار دارد). حالا خط `font-family: 'Lobster';` را بین آکولادها اضافه کنید و صفحه وب را دوباره بارگیری کنید: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { color: #C25100; font-family: 'Lobster'; } +``` + +![تصویر 14.3](images/font.png) + +عالی! + +همانطور که در بالا ذکر شد CSS دارای مفهوم کلاس است. کلاس‌ها به شما اجازه می‌دهند تا بخشی از کد HTML را نامگذاری کنید و تنها فرمت این قسمت از کد را تغییر بدهید، بدون اینکه به سایر قسمت‌ها آسیبی برسد. کلاس‌ها می‌توانند فوق‌العاده مفید باشند! شاید شما دو div دارید که کاری متفاوت انجام می دهند (مانند header و post). یک کلاس می‌تواند به شما کمک کند آن‌ها را متفاوت نگاه کنید. + +به همین ترتیب جلو بروید و برخی بخش‌های کد HTML را نام گذاری کنید. بخش `header` را که شامل header وب‌سایت شماست با کد زیر جابجا کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +و اکنون کلاس `post` را به `article` اضافه کنید که حاوی یک پست وبلاگ است. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +ما اکنون بلوک‌های معرف را به انتخاب‌گرهای مختلف اضافه خواهیم کرد. انتخابگرهایی که با `.` آغاز می‌شوند مربوط به کلاس‌ها هستند. آموزش‌ها و توضیحات بسیار خوبی درباره CSS در اینترنت وجود دارد که می‌تواند به شما در درک کد زیر کمک کند. حالا این قطعه کد را در فایل `blog/static/css/blog.css` کپی کنید: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +سپس کد HTML زیر را که نمایش پست‌ها با اسامی کلاس‌ها را نشان می‌دهد: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +در فایل `blog/templates/blog/post_list.html` با قطعه کد زیر عوض کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +این فایل‎‌ها را ذخیره کنید و وبسایت خود را دوباره بارگیری کنید. + +![تصویر 14.4](images/final.png) + +یووهو! به نظر عالی می‌آید، اینطور نیست؟ به کدی که اضافه کردیم نگاه کنید تا محلی که کلاس ها را در HTML اضافه و در CSS استفاده کرده ایم پیدا کنید. اگر بخواهید نوشته تاریخ ها را فیروزه ای رنگ کنید کجا را باید تغییر دهید؟ + +نگران نباشید کمی با این CSS کار کنید و سعی کنید برخی از چیزها را تغییر دهید. بازی با CSS می‌تواند به شما کمک کند که بفهمید هر بخش چگونه کار می‌کند. اگر چیزی را خراب کردید، نگران نباشید، همیشه می‌توانید این تغییرات را به حالت قبل برگردانید! + +ما اکیداً گذراندن دوره‌های آموزشی آنلاین "Basic HTML & HTML5" و "Basic CSS" را در [freeCodeCamp](https://learn.freecodecamp.org/) توصیه می‌کنیم. این دوره‌ها به شما کمک خواهد کرد تا همه چیزهایی که برای زیباتر کردن وبسایت خود با HTML و CSS لازم دارید یاد بگیرید. + +برای فصل بعدی آماده هستید؟! :) \ No newline at end of file diff --git a/fa-IR/deploy/README.md b/fa-IR/deploy/README.md new file mode 100644 index 00000000000..f9ff5947e75 --- /dev/null +++ b/fa-IR/deploy/README.md @@ -0,0 +1,246 @@ +# مرحله منتشر کردن! + +> **توجه داشته باشید** که قسمت‌های پیش رو ممکن است کمی سخت به نظر برسد. نا امید نشوید و این بخش را تا آخر ادامه دهید، یکی از مهم‌ترین قسمت‌های توسعه وب سایت منتشرکردن یا Deploy می‌باشد. این فصل در وسط آموزش قرار گرفته است، بنابراین مربی شما می‌تواندبه شما در راه اندازی آنلاین وبسایتتان کمک کند. این به این معنی است که شما می‌توانید به تنهایی ادامه‌ی تمرین خود را به اتمام برسانید حتی اگر زمان کارگاه به پایان برسد. + +تا به اینجا وب سایت شما فقط در رایانه شما قابل مشاهده است. حالا شما یاد خواهید گرفت که چگونه آن را دیپلوی کنید! دیپلوی یعنی فرآیند انتشار پروژه شما در اینترنت، تا سایرین بتوانند در نهایت پروژه شما را ببینند. :) + +همانطور که یاد گرفتید، وب سایت باید بر یک سرور جای بگیرد. سرورهای زیادی در اینترنت وجود دارد، ما قصد داریم از [PythonAnywhere](https://www.pythonanywhere.com/) استفاده نماییم. PythonAnywhere برای پروژه‌های کوچک که بازدید‌کنندگان خیلی زیادی ندارند رایگان است بنابراین در حال حاضر برای شما مناسب است. + +سرویس خارجی دیگری که ما استفاده می‌کنیم [گیت هاب](https://www.github.com) است که سرویس میزبانی کد است. سرویس‌های دیگری نیز وجود دارد، اما تقریباً این روزها همه برنامه نویسان اکانت گیت هاب دارند و الان شما هم خواهید داشت! + +این سه مکان برای شما مهم خواهد بود. کامپیوتر محلی شما جایی است که شما در حال توسعه و تست هستید. هنگامی که شما تغییرات را اعمال کردید، یک نسخه از برنامه خود را در گیت هاب قرار می‌دهید. وب سایت شما در PythonAnywhere خواهد بود و شما آن را با یک کپی جدید از کدهای خود که از گیت هاب گرفته‌اید، به روز رسانی خواهید کرد. + +# گیت + +> **نکته** اگر بخش [نصب و راه‌اندازی](../installation/README.md) را انجام داده‌اید، نیازی نیست که دوباره این بخش را انجام دهید. می‌توانید از این بخش رد شده و ساختن مخزن گیت را شروع کنید. + +{% include "/deploy/install_git.md" %} + +## ایجاد مخزن گیت + +نرم افزار گیت تغییرات یک مجموعه فایل که در جایی به نام مخزن (به طور مخفف repo) وجود دارند را ردگیری می‌کند. بیایید یکی برای پروژه خودمان بسازیم. کنسول خود را باز کنید و این دستورات را در پوشه `djangogirls` اجرا کنید: + +> ** توجه ** قبل از شروع به کار موقعیت پوشه‌ای را که در آن هستید با دستور `pwd` (در سیستم عامل Mac OS X / Linux) یا `cd` (در ویندوز) بفهمید. شما باید در پوشه `djangogirls` باشید. + +{% filename %}خط فرمان{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +راه اندازی مخزن گیت کاری است که ما برای هر پرژه فقط یک بار انجام می‌دهیم (لازم نیست مجدداً نام کاربری و ایمیل را وارد کنید). + +گیت هاب تغییرات روی تمام فایل‌ها و پوشه های زیرمجموعه این پوشه را پیگیری می‌کند، اما برخی فایل‌هایی که می‌خواهیم آن‌ها را نادیده بگیریم نیز وجود دارند. ما این کار را با ایجاد یک فایل به نام `.gitignore` در پوشه پایه انجام می‌دهیم. ویرایشگر خود را باز کنید و یک فایل جدید با محتویات زیر ایجاد کنید: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +و آن را در پوشه "djangogirls" با نام `.gitignore` ذخیره کنید. + +> ** توجه** نقطه در ابتدای نام فایل مهم است! اگر مشکلی در ایجاد آن دارید (به عنوان مثال Mac شما دوست ندارد فایل هایی را بسازید که با نقطه شروع می‌شود)، پس از ویژگی save as استفاده کنید که به کمک آن می‌توانید این نوع فایل‌ها را ذخیره کنید. و مطمئن باشید که هیچ پسوندی مانند `.txt` یا `.py` در انتهای فایل نگذاشته باشید نام این فایل فقط باید `.gitignore` باشد تا توسط Git شناسایی شود. لینوکس و MacOS با فایل‌هایی که با `.` شروع شوند (مانند `.gitignore`) مانند یک فایل مخفی شده برخورد می‌کند و دستور `ls` به طور معمول آن‌ها را نشان نمی‌دهد. به جای آن از دستور `ls -a` برای دیدن فایل `.gitignore` استفاده کنید. +> +> **توجه** یکی از فایل‌هایی که در فایل `.gitignore` مشخص شده است فایل `db.sqlite3` است. این فایل پایگاه داده محلی شماست جایی که تمام اطلاعات مربوط به کاربر و پست‌های وبلاگ شما در آن ذخیره می‌شود. ما از روش استاندارد برنامه نویسی استفاده خواهیم کرد به این معنی که ما از پایگاه داده‌های متفاوتی برای توسعه بر روی کامپیوتر محلی و سپس وبسایت اصلی که روی PythonAnywhere هست استفاده خواهیم کرد. پایگاه داده بر روی PythonAnywhere می‌تواند SQLite باشد همانند آنچه بر روی کامپیوتر خود از آن استفاده می‌کنید اما معمولاً از پایگاه داده MySQL برای وبسایت اصلی استفاده می‌کنیم که می‌تواند تعداد بسیار زیاد بازدیدکننده از سایت را مدیریت کند. علاوه بر این حذف کردن فایل SQLite در کپی مربوط به GitHub به این معنی است که تمام پست‌های وبلاگی و superuser هایی که تا الان ساخته‌اید فقط روی کامپیوتر خودتان مورد استفاده خواهد بود و برای محیط اصلی وبسایت باید دوباره آن‌ها را بسازید. شما باید از پایگاه داده محلی خود به عنوان یک زمین بازی خوب استفاده کنید که در آن می‌توانید چیزهای مختلف را آزمایش کنید و نگرانی پاک کردن پست‌های اصلی از وبلاگ را نداشته باشید. + +ایده خوبی است که همیشه قبل از زدن دستور `git add` یا هر وقت که مطمئن نیستید چه چیزی تغییر کرده، دستور `git status` را بزنید. این کار کمک می‌کند که از هر نوع غافلگیری مانند اضافه کردن یا commit کردن فایل اشتباه، جلوگیری شود. دستور `git status` اطلاعاتی در مورد فایل‌های ردگیری نشده untracked، اصلاح شده modified، استیج شده staged و نیز درمورد وضعیت شاخه ای که در آن هستیم می‌دهد. خروجی باید شبیه به موارد زیر باشد: + +{% filename %}خط فرمان{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +و در نهایت ما تغییرات را ذخیره می‌کنیم. به کنسول خود بروید و این دستورات را اجرا کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ git add . + $ 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](https://www.github.com) بروید و یک حساب کاربری رایگان برای خود بسازید. اگر این کار را در کارگاه برای اولین بار انجام می‌دهید حواستان باشد که رمز عبور خود را حفظ کنید یا به نر‌م‌افزار مدیریت رمز عبور خود بسپرید. + +حالا یک مخزن یا repository بسازید و نام آن را "my-first-blog" بگذارید. گزینه "initialize with a README" را علامت نخورده باقی بگذارید و هم چنین گزینه .gitignore را هم خالی بگذارید (ما بعداً آن را اضافه خواهیم کرد). هم چنین گزینه License را None بگذارید. + +![](images/new_github_repo.png) + +> **توجه** نام `my-first-blog` مهم است. شما می‌توانید اسم دیگری انتخاب کنید اما از این اسم زیاد استفاده خواهیم کرد و به یاد داشته باشید که اگر اسم دیگری گذاشتید هرجا لازم بود اسم انتخابی خود را استفاده کنید. احتمالاً راحت‌تر است که از همین اسم `my-first-blog` استفاده نمایید. + +در صفحه بعد شما URL مخزن خود را خواهید دید که در برخی دستورات بعدی از آن استفاده خواهیم کرد: + +![](images/github_get_repo_url_screenshot.png) + +حالا وقت آن است که مخزن Git روی کامپیوتر شما را به مخزن موجود در Github وصل کنیم. + +خط زیر را در کنسول خود تایپ کنید (`` را با نام کاربری و گذر واژه خود که در GitHub تعریف کرده اید عوض کنید. علامت‌های کوچکتر و بزرگتر را استفاده نکنید. URL باید دقیقاً همان آدرسی باشد که کمی قبل‌تر دیده‌اید): + +{% filename %}خط فرمان{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +وقتی شما فایلی را به GitHub می‌فرستید یا push می‌کنید نام کاربری و گذرواژه از شما پرسیده می‌شود (ممکن است در همان کنسول خط فرمان یا در یک پنجره جدید از شما پرسیده شود) پس از وارد کردن اطلاعات ورود، چیزی شبیه به این خواهید دید: + +{% filename %}خط فرمان{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +کد شما الان روی GitHub است. بروید و آن را کنترل کنید! خواهید دید که کدهای شما در جای خوبی است. پروژه [Django](https://github.com/django/django)، دوره آموزشی [Django Girls](https://github.com/DjangoGirls/tutorial) و بسیاری نرم‌افزارهای متن باز فوق العاده دیگر هم، کدهایشان را در GitHub قرار داده‌اند. :) + +# تنظیم کردن وبلاگ بر روی PythonAnywhere + +## یک حساب کاربری بر روی PythonAnywhere بسازید + +> **توجه** شما ممکن است کمی قبل‌تر و در مراحل نصب یک حساب کاربری در PythonAnywhere درست کرده باشید. اگر چنین است نیاز نیست که حساب کاربری دیگری بسازید. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## وبسایت‌مان را بر روی PythonAnywhere تنظیم کنیم + +با کلیک کردن بر روی لوگو و انتخاب گزینه شروع یک کنسول "Bash" به [داشبورد PythonAnywhere ](https://www.pythonanywhere.com/) بروید. این محیط خط فرمان مخصوص PythonAnywhere است، شبیه آنچه در کامپیوتر خود دارید. + +![بخش 'New Console' در صفحه وبسایت PythonAnywhere با دکمه‌ای برای 'bash'](images/pythonanywhere_bash_console.png) + +> **توجه** PythonAnywhere بر مبنای لینوکس است، بنابراین اگر روی ویندوز کار می‌کنید این محیط خط فرمان با آنچه در ویندوز دارید کمی متفاوت است. + +منتشر کردن یک اپلیکیشن تحت وب بر روی PythonAnywhere شامل آوردن کدها از GitHub و تنظیم کردن PythonAnywhere برای تشخیص آن و اجرا کردنش به عنوان یک برنامه تحت وب است. روش‌های غیرخودکار برای این کار وجود دارد اما PythonAnywhere یک ابزار کمکی دارد که همه این کارها را برای شما انجام می‌دهد. اجازه بدهید اول از همه این ابزار را نصب کنیم: + +{% filename %}خط فرمان PythonAnywhere {% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +این دستور باید چیزهایی شبیه به `Collecting pythonanywhere` بر روی صفحه نشان دهد و در انتها نیز این پیغام `Successfully installed (...) pythonanywhere- (...)` نمایش داده خواهد شد. + +حالا ما برنامه کمکی را اجرا می‌کنیم تا به طور اتوماتیک برنامه ما را از GitHub بخواند. خطوط زیر را در کنسول PythonAnywhere بنویسید (فراموش نکنید که نام کاربری GitHub را به جای `` بنویسید در نتیجه URL شما مانند URL اختصاصی شما در GitHub میشود): + +{% filename %}خط فرمان PythonAnywhere {% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +همینطور که به اجراشدن آن نگاه می‌کنید می‌توانید بفهمید که چه کاری انجام می‌دهد: + +- دانلود کردن کد شما از GitHub +- ساختن یک محیط مجازی virtualenv بر روی PythonAnywhere شبیه آنچه که بر روی کامپیوتر خود داشتید +- به روزرسانی برخی از تنظیمات شما با تنظیمات مورد نیاز برای انتشار +- تنظیم کردن یک دیتابیس در PythonAnywhere با استفاده از دستور `manage.py migrate` +- تنظیم کردن فایل‌های ثابت شما (بعداً درمورد آن‌ها یاد خواهیم گرفت) +- و در نهایت تنظیم کردن PythonAnywhere برای ارائه اپلیکیشن شما از طریق API خودش + +در PythonAnywhere تمام این مراحل اتوماتیک انجام می‌شود اما برای سایر سرورها شما باید دقیقا تمام این اقدامات را انجام دهید. + +مهم‌ترین چیزی که اینجا باید به آن توجه کنید آن است که پایگاه داده شما در اینجا از چیزی که بر روی کامپیوتر خود دارید کاملا مستقل است در نتیجه ممکن است اینجا حساب کاربری ادمین یا پست‌های متفاوتی نسبت به کامپیوتر شخصی خود داشته باشید. در نتیجه همان طور که بر روی کامپیوتر خودمان انجام داده ایم باید یک کاربر admin با دستور `createsuperuser` بسازیم. PythonAnywhere به صورت اتوماتیک محیط مجازی یا virtulenv شما را فعال کرده است درنتیجه تنها چیزی که لازم دارید این است که خط زیر را اجرا کنید: + +{% filename %}خط فرمان Python Anywhere{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +مشخصات کاربر ادمین را وارد کنید. می‌توانید این اطلاعات را شبیه اطلاعات ادمین که قبلاً در کامپیوتر خود زده‌اید در نظر بگیرید مگر اینکه بخواهید گذره واژه امن‌تری در PythonAnywhere در نظر بگیرید. + +حالا اگر بخواهید می‌‌توانید نگاهی به کدهای خود در PythonAnywhere بیندازید دستور `ls` را بزنید: + +{% filename %}خط فرمان PythonAnywhere{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.pytests.py static + templates views.py + + +علاوه بر این می‌توانید به صفحه File بروید و به کمک مرورگر فایل پیش‌ساخته که در PythonAnywhere قرار داده شده به فایل‌های خود نگاهی بیاندازید. از صفحه کنسول و به کمک کلید منو در گوشه بالا و سمت راست، می توانید به سایر صفحات PythonAnywhere بروید. وقتی شما در یک صفحه هستید، نزدیک به بالای صفحه، لینک‌هایی به سایر صفحات وجود دارد. + +## اکنون آنلاین هستید! + +وب‌سایت شما باید الان به طور عمومی در اینترنت منتشر شده باشد! از طریق صفحه "Web" در PythonAnywhere لینک به این صفحه را پیدا کنید. شما می‌توانید این صفحه را با هر کسی به اشتراک بگذارید. :) + +> **توجه** این یک تمرین ابتدایی است و ما در هنگام انتشار، برخی میانبرهایی را استفاده کرده‌ایم که از جنبه امنیت وبسایت، روش‌های ایده‌آلی نیستند. هرگاه تصمیم گرفتید که این پروژه یا پروژه دیگری را بسازید، باید به راهنمایی‌های امنیتی موجود در [چک لیست انتشار جنگو](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) نگاهی بیندازید. + +## نکات عیب‌یابی + +اگر شما با خطایی در هنگام اجرا کردن دستور `pa_autoconfigure_django.py` مواجه شدید ممکن است به دلایل زیر باشد: + +- فراموشی در ساخت توکن API در PythonAnywhere. +- اشتباه در URL مربوط به GitHub +- اگر خطایی با این مضمون *"Could not find your settings.py"* مشاهده کردید، احتمالاً تمام فایل‌های خود را به Git اضافه نکرده‌اید یا همه آن‌ها را (به کمک دستور push) به GitHub نفرستاده‌اید. به بخش Git در بالا نگاهی دوباره بیندازید +- اگر قبلاً حساب کاربری در PythonAnywhere داشته‌اید و خطای collectstatic دریافت می‌کنید احتمالاً نسخه‌های قدیمی‌تر SQLite (مثلاً 3.8.2) را در حساب کاربری خود دارید. در این موارد، یک حساب کاربری جدید بسازید و دستورات مربوط به PythonAnywhere را دوباره بزنید. + +اگر هنگام مراجعه به وبسایت خطایی مشاهده کردید اولین جا برای بررسی و عیب یابی نگاه کردن به بخش **error log** است. حتماً در صفحه ["Web"](https://www.pythonanywhere.com/web_app_setup/) در PythonAnywhere لینکی به این بخش پیدا خواهید کرد. نگاه کنید که آیا پیغام خطایی در این صفحه وجود دارد؛ آخرین پیغام‌ها در پایین‌ترین خط ها است. + +علاوه بر این دستورالعمل‌های عیب‌یابی عمومی‌تری هم در [صفحه راهنمای سایت PythonAnywhere](http://help.pythonanywhere.com/pages/DebuggingImportError) وجود دارد. + +و به یاد داشته باشید که مربی شما اینجاست تا به شما کمک کند! + +# وبسایت خود را بررسی کنید! + +صفحه اصلی سایت شما باید "It worked" را نشان دهد همانطور که بر روی کامپیوتر خودتان کار می‌کرد. سعی کنید ` /admin/ ` را به انتهای آدرس اینترنتی اضافه کنید و به سایت مدیریت برسید. با نام کاربری و گذرواژه خود وارد شوید خواهید دید که می‌توانید پست جدیدی ایجاد کنید. به یاد داشته باشید که پست‌هایی که در پایگاه داده کامپیوتر خود ایجاد کرده اید بر روی وبسایت آنلاین شما منتقل نشده است. + +وقتی چند پست جدید ایجاد کردید به تنظیمات بر روی کامپیوتر خود (local و نه تنظیمات روی PythonAnywhere) برگردید. از اینجا می‌توانید تنظیمات محلی را تغییر دهید. این یک روش رایج در توسعه وبسایت است؛ تغییرات را روی کامپیوتر خود اعمال کنید، آن‌ها را به GitHub بفرستید و سپس این تغییرات را از گیتهاب، بر روی وب سرور کپی کنید. این روش کمک می‌کند که بدون ایجاد خرابی در وبسایت آنلاین بتوان آن را به روز رسانی کرد. جالب نیست؟ + +یک *خسته نباشید* حسابی به خودتان بگویید! راه اندازی سرور یکی از مهارتی‌ترین بخش‌های توسعه وبسایت است و گاهی برای برخی افراد روزها زمان می‌برد تا بتوانند آن را راه اندازی کنند. اما شما توانستید سایت خود را بر روی اینترنت واقعی راه اندازی کنید! \ No newline at end of file diff --git a/fa-IR/deploy/install_git.md b/fa-IR/deploy/install_git.md new file mode 100644 index 00000000000..ff86d8911c0 --- /dev/null +++ b/fa-IR/deploy/install_git.md @@ -0,0 +1,52 @@ +گیت یک "سیستم کنترل نسخه" است که توسط بسیاری از برنامه‌نویسان مورد استفاده قرار می‌گیرد. این نرم‌افزار می‌تواند تغییرات روی فایل‌ها را در طول زمان دنبال کند بنابراین می‌توانید نسخه خاصی را بعداً بازیابی کنید. این قابلیت تقریباً شبیه ابزار "track changes" در برنامه‌های ویرایش متن (مانند Microsoft Word و LibreOffice Writer) است اما به مراتب از آن‌ها قویتر است. + +## نصب گیت + + + +برای نصب گیت می‌توانید آن را از [git-scm.com](https://git-scm.com/) دانلود کنید. همه جا میتوانید کلید next را بزنید به غیر از دو جا: جایی که در مورد ویرایشگر متن از شما می‌پرسد شما باید ویرایشگر Nano را انتخاب کنید و در مرحله‌ای که عنوان آن "Adjusting your PATH environment" است، گزینه "Use Git and optional Unix tools from the Windows Command Prompt" (گزینه آخر) را انتخاب کنید. در بقیه موارد، پیش فرض‌ها مناسب هستند. گزینه "Checkout Windows-style, commit Unix-style line endings" را انتخاب کنید. + +فراموش نکنید که بعد از اینکه نصب به پایان رسید command prompt یا PowerShell را از نو باز کنید. + + + +گیت را از [git-scm.com](https://git-scm.com/) دانلود کنید و دستورالعمل‌ها را دنبال کنید. + +> ** نکته **اگر شما از OS X نسخه 10.6، 10.7 یا 10.8 استفاده می‌کنید باید GIT را از اینجا نصب کنید: [ نصب Git برای OS X Snow Leopard ](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/fa-IR/deploy/signup_pythonanywhere.md b/fa-IR/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..919b24ce459 --- /dev/null +++ b/fa-IR/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere سرویسی است که برای اجرای کدهای نوشته شده با پایتون در سرورهای ابری استفاده می‌شود. ما از آن برای میزبانی سایت خود و قرار دادن آن بر روی اینترنت استفاده خواهیم کرد. + +بلاگی که در حال ساختن آن هستیم را بر روی PythonAnywhere قرار خواهیم داد. برای استفاده از سرویس PythonAnywhere میتوانید به صورت رایگان به عنوان تازه کار در آن ثبت نام کنید (ثبت نام به صورت تازه کار برای کار ما کفایت می کند. نیازی به ورود کارت اعتباری نیست). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![صفحه ثبت نام PythonAnywhere دارای امکان ثبت نام رایگان برای کاربران تازه کار می باشد](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **نکته:** هنگام انتخاب نام کاربری خود به این نکته توجه داشته باشید که آدرس بلاگ شما با نام کاربری شما به صورت `yourusername.pythonanywhere.com` مشخص خواهد شد. بنابراین علاوه بر استفاده از نام خود به عنوان نام کاربری، می‌توانید از یک اسم دلخواه برای بلاگ خود استفاده کنید. هچینین رمز عبور خود را به خاطر داشته باشید. + +## ایجاد API توکن PythonAnywhere + +این کار را فقط یکبار هنگام شروع انجام خواهید داد. پس از اینکه در PythonAnywhere ثبت نام کردید به داشبورد خود هدایت خواهید شد. در سمت راست بالای صفحه بر روی Account خود کلیک کنید: + +![لینک Account در سمت راست بالای صفحه](../deploy/images/pythonanywhere_account.png) + +سپس به تب "API token" رفته و "Create new API token" را بزنید. + +![تب API token در صفحه Account](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/fa-IR/django/README.md b/fa-IR/django/README.md new file mode 100644 index 00000000000..9870bd4f5a8 --- /dev/null +++ b/fa-IR/django/README.md @@ -0,0 +1,27 @@ +# جنگو چیست؟ + +جنگو (*جَنگو*) یک فریم‌ورک تحت وب رایگان و متن بازopen source است که با زبان پایتون نوشته شده‌است. یک فریم ورک تحت وب، دارای مجموعه‌ای از ابزارهاست که به شما کمک می‌کنند تا یک وب سایت را سریع‌تر و راحت‌تر توسعه دهید. + +هنگامی که در حال ساخت یک وب سایت هستید، شما همیشه به مجموعه ای از اجزای مشابه نیاز دارید. به شرح زیر: یک روش برای کنترل کردن احراز هویت کاربر (ثبت نام ، ورود به حساب کاربری ، خروج از حساب کاربری) ، یک پنل مدیریت برای وب سایت خود ، فرم ها ، روشی برای آپلود فایل ها و غیره. + +خوشبختانه خیلی وقت پیش، افرادی متوجه این موضوع شدند که هنگام ساختن یک سایت جدید، توسعه دهندگان وب با مشکلات مشابهی روبرو می‌شوند، بنابراین آنها تیمی را تشکیل دادند که به راحتی اجزای کار را در اختیار شما قرار می‌دهد که شما بتوانید به راحتی از آنها استفاده کنید ودر نهایت فریم ورک‌ها را ساختند (جنگو یکی از آن هاست). + +فریم ورکها به این دلیل به وجود آمده اند که دیگر نیازی نباشد شما از اول چرخ را بسازید و به شما کمک می کند تا به راحتی سایت خود را بسازید. + +## چرا شما به یک فریم ورک نیاز دارید؟ + +برای درک بهتر چگونگی عملکرد جنگو لازم است نگاه دقیق‌تری به سرورها بیندازیم. اولین چیزی که سرور نیاز دارد بداند این است که شما می‌خواهید سرور برای شما یک وب پیج را ارائه کند. + +حالا یک صندوق پست (port) را تصور کنید که منتظر دریافت نامه‌ها (requests) است. این کار توسط وب سرور انجام خواهد گرفت. وب سرور نامه را خوانده و پاسخ مربوطه را به وب پیج می فرستد. اما هنگامی که شما می‌خواهید چیزی را ارسال کنید، به محتوا احتیاج دارید. و جنگو همانی است که به شما برای ایجاد محتوا کمک می‌کند. + +## زمانی که فردی از سرور شما یک وبسایت را درخواست می‌کند، چه اتفاقی می‌افتد؟ + +هنگامی که یک درخواست به وب سرور می آید، به جنگو انتقال داده می شود و جنگو تلاش می‌کند بفهمد که دقیقاً چه چیزی درخواست شده است. در ابتدا آدرس وب پیج را می‌گیرد و سعی می‌کند تشخیص دهد چه کاری باید انجام دهد. این بخش توسط **urlresolver** جنگو انجام می‌گیرد (آدرس وبسایت URL یا Uniform Resource Locator نامیده می‌شود به این دلیل *urlresolver* یا تجزیه کننده URL نام با مسمایی است). خیلی سیستم هوشمندی نیست فقط یک لیست از الگوها را می‌گیرد و سعی می‌کند درخواست را با یکی از این الگوها مطابقت دهد. جنگو الگوها را از بالا به پایین بررسی می‌کند و اگر الگویی مشابه درخواست پیدا کرد، آن درخواست را به تابع مرتبط با آن الگو (که * view * نامیده می‌شود) ارسال می‌کند. + +یک پستچی را با یک نامه تصور کنید. او در خیابان راه می‌رود و پلاک هر خانه را با پلاک نوشته شده روی نامه مقایسه می‌کند. اگر مطابقت داشته باشد، نامه را در آنجا می گذارد. این روش کار urlresolver است! + +در تابع * view*، تمام چیزهای جالب اتفاق می‌افتد: ما می‌توانیم به یک پایگاه داده نگاه کنیم تا اطلاعاتی را جستجو کنیم. شاید کاربر درخواست تغییر در داده را داشته باشد؟ مانند درخواست‌هایی که در یک نامه فرستاده می‌شوند: "لطفا شرح شغل من را تغییر دهید". تابع * view* می‌تواند بررسی کند که آیا شما مجاز به انجام این کار هستید، و سپس شرح شغل را برای شما به روز رسانی کرده و یک پیام را ارسال کند: "انجام شد!" سپس تابع *view * یک پاسخ ایجاد می‌کند و جنگو می‌تواند آن را به مرورگر وب کاربر ارسال کند. + +توضحیحات بالا کمی ساده شده‌اند اما شما نیازی ندارید که همه ریزه‌کاری‌های فنی را بدانید. یک درک کلی از فرآیند کافی است. + +پس به جای آن که بیش از این سراغ جزییات برویم می‌خواهیم با جنگو چیزی بسازیم و بخش‌های مهم آن را در این مسیر یاد بگیریم! \ No newline at end of file diff --git a/fa-IR/django_admin/README.md b/fa-IR/django_admin/README.md new file mode 100644 index 00000000000..e571d29a120 --- /dev/null +++ b/fa-IR/django_admin/README.md @@ -0,0 +1,57 @@ +# پنل مدیریت در جنگو + +برای اضافه کردن، ویرایش و حذف پست‌هایی که به تازگی مدلشان را درست کرده‌ایم، از جنگو ادمین یا پنل مدیریت جنگو استفاده خواهیم کرد. + +فایل `blog/admin.py` را در ویرایشگر کد باز کنید و محتوای آن را با خطوط زیر عوض کنید: + +{% filename %}blog/admin.py{% endfilename %} + +```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/ را تایپ کنید. شما یک صفحه لاگین را به شکل زیر می‌بینید: + +![صفحه لاگین](images/login_page2.png) + +برای ورود به سیستم، باید یک کاربر *superuser* ایجاد کنید - یک حساب کاربری که بر روی همه چیز در سایت کنترل داشته باشد. به محیط خط فرمان بازگردید و دستور `python manage.py createsuperuser` را تایپ کنید و Enter را فشار دهید. + +> به یاد داشته باشید، برای نوشتن دستورات جدید در حالی که وب سرور در حال اجرا است، یک پنجره ترمینال جدید را باز کرده و محیط مجازی خود را فعال کنید. ما در مورد نحوه نوشتن دستورات جدید در بخش **راه اندازی وب سرور** از فصل **اولین پروژه جنگو شما!** صحبت کردیم. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +هنگام درخواست، نام کاربری (با حروف کوچک و بدون فاصله)، آدرس ایمیل و رمز عبور را تایپ کنید. **نگران نباشید که تایپ شدن گذر واژه را نمی‌بینید، همانطور است که باید باشد.** گذرواژه را وارد کنید و `Enter` را بزنید. خروجی باید مانند این باشد (که در آن نام کاربری و ایمیل خود را باید ببینید): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +به مرورگر خود برگردید و با نام کاربری که انتخاب کرده اید وارد شوید. شما باید داشبورد مدیریت جنگو را ببینید. + +![جنگو ادمین](images/django_admin3.png) + +به بخش Post بروید و کمی با آن کار کنید. پنج یا شش پست وبلاگی بسازید. نگران محتوای پست‌ها نباشید، این پست‌ها فقط به صورت محلی و برای شما نمایش داده خواهد شد. می‌توانید برای صرفه جویی در وقت از جایی مطالبی در آن کپی کنید. :) + +اطمینان حاصل کنید که حداقل برای دو یا سه پست (اما نه همه پست‌ها) تاریخ انتشار را تعیین کنید. بعداً مفید خواهد بود. + +![پنل مدیریت در جنگو](images/edit_post3.png) + +اگر می‌خواهید در مورد پنل مدیریت جنگو بیشتر بدانید باید مستندات جنگو را نگاه کنید: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +احتمالاً الان وقت مناسبی است تا قهوه یا چای بنوشید یا چیزی برای خوردن پیدا کنید تا دوباره سرحال شوید. شما اولین مدل جنگو را ایجاد کردید و شایسته یک استراحت کوتاه هستید! \ No newline at end of file diff --git a/fa-IR/django_forms/README.md b/fa-IR/django_forms/README.md new file mode 100644 index 00000000000..4f696368d76 --- /dev/null +++ b/fa-IR/django_forms/README.md @@ -0,0 +1,479 @@ +# فرم در جنگو + +آخرین چیزی که می‌خواهیم در وب سایت مان انجام دهیم ایجاد یک راه خوب برای اضافه کردن و ویرایش پست‌های وبلاگ است. `ادمین ` جنگو خوب است، اما سخت است که آن را زیبا یا سفارشی کنیم. با ` فرم‌ها ` ما کنترل کاملی بر روی صفحه خود داریم. تقریباً می‌توانیم هرکاری که بخواهیم انجام دهیم! + +ویژگی فرم‌ها در جنگو این است که ما می‌توانیم یکی را از ابتدا تعریف کنیم یا از `ModelForm`استفاده کنیم که نتیجه فرم را به صورت مدل ذخیره می‌کند. + +این دقیقا همان چیزی است که ما می‌خواهیم انجام دهیم: ما یک فرم را برای مدل ` Post` ایجاد خواهیم کرد. + +مانند هر بخش مهمی از جنگو، فرم‌ها فایل خود را دارند: ` forms.py`. + +ما باید یک فایل با این نام در پوشه ` blog` ایجاد کنیم. + + blog + └── forms.py + + +خوب، اجازه دهید آن را در ویرایشگر کد باز کنیم و خطوط زیر را تایپ کنیم: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +باید در ابتدا فرم‌های جنگو را فراخوانی کنیم (`from django import forms`) سپس مدل مربوط به `Post` را نیز فراخوانی کنیم(`from .models import Post`). + +` PostForm`، همانطور که احتمالاً حدس زده اید، نام فرم ما است. ما باید به جنگو بگوییم که این فرم یک نوع `ModelForm` است (بنابراین جنگو برای ما چند کار جادویی انجام خواهد داد) - `forms.ModelForm` مسئول انجام این کارها است. + +بعد از این، ما `class Meta` را داریم، جایی که به جنگو می‌گویم که کدام مدل باید برای ایجاد این فرم (`model = Post`) استفاده شود. + +در نهایت می‌توانیم بگوییم که کدام بخش‌ (بخش‌ها) باید در فرم ما باشد. در این سناریو ما تنها `title` و `text` را می‌خواهیم نشان دهیم - `author` باید فردی باشد که در حال حاضر وارد شده است (شما!) و `created_date` تاریخ ایجاد یک پست جدید است که باید به طور خودکار تنظیم شود، درست است؟ + +و همین! تمام مواردی که اکنون باید انجام دهیم، استفاده از فرم در یک *view* و نمایش آن در تمپلیت است. + +بنابراین یک بار دیگر یک لینک، یک URL، یک view و یک تمپلیت ایجاد خواهیم کرد. + +## لینک به یک صفحه با فرم + +قبل از آنکه لینک را اضافه کنیم، لازم است آیکونی را به عنوان دکمه برای این لینک اضافه کنیم. برای این دوره آموزشی فایل [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) را دانلود کنید و آن را در پوشه `blog/templates/blog/icons/` ذخیره کنید + +> نکته: برای دانلود فایل SVG منو زمینه‌ای مربوط به آن را باز کنید (معمولاً به کمک راست کلیک بر روی آن) و بعد گزینه "Save link as" را انتخاب کنید. در پنجره‌ای که باز می‌شود آدرس محلی که می‌خواهید فایل را ذخیره کنید، مشخص کنید، به پوشه `djangogirls` که پروژه جنگو شما در آن است بروید و پوشه `blog/templates/blog/icons/` را پیدا کنید و فایل را در آن ذخیره کنید. + +وقت آن است که فایل `blog/templates/blog/base.html` را در ویرایشگر متن خود باز کنید. حالا می‌توانیم از فایل آیکون در تمپلیت base به شکل زیر استفاده کنیم. در عنصر `div` که در بخش `header` قرار دارد، لینکی قبل از عنصر `h1` اضافه خواهیم کرد: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +توجه داشته باشید که ما می‌خواهیم نام ویو جدید را `post_new` بگذاریم. آیتم [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) توسط [Bootstrap Icons](https://icons.getbootstrap.com/) ارائه می‌شود و علامتی مانند یک صفحه به همراه یک علامت به اضافه، نشان خواهد داد. ما از یک هدایت‌کننده جنگو یا Django template directive، به اسم `include` استفاده می‌کنیم. این هدایت‌کننده محتوای یک فایل را به تمپلیت جنگو تزریق می‌کند. مرورگر وب به خوبی می‌تواند این نوع از محتوا را بدون پردازش‌های اضافه، مدیریت کند. + +> شما می‌توانید تمام آیکون‌های بوتسترپ را از [اینجا](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip) دانلود کنید. فایل را از حالت زیپ خارج کنید و همه تصاویر را در پوشه‌ای به نام `icons` در داخل پوشه `blog/templates/blog/` قرار دهید. به این روش شما می‌توانید به آیکونی مانند `pencil-fill.svg` از طریق آدرس `blog/templates/blog/icons/pencil-fill.svg`، دسترسی داشته باشید + +بعد از اصلاح این خط، فایل شما باید به این شکل باشد: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +پس از ذخیره و بازخوانی صفحه http://127.0.0.1:8000 شما با یک خطای شناخته شده `NoReverseMatch` مواجه خواهید شد، درست است؟ بسیار عالی! + +## آدرس اینترنتی + +فایل `blog/urls.py` را باز کرده و کد زیر را به آن اضافه می‌کنیم: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +و در نهایت کد ما بصورت زیر خواهد بود: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +از آنجایی که ویوی `post_new` را پیاده سازی نکرده ایم، هنگامی که سایت را ریفرش کنیم با خطای `AttributeError` مواجه خواهیم شد. پس باید ویوی مربوطه را نیز بسازیم: + +## ویو post_new + +زمان آن است که فایل `blog/views.py` را در ویرایشگر کد باز کنید و خطوط زیر را در ردیف `from` ها اضافه کنید: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +و حالا *view* ما: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +برای ایجاد یک فرم جدید`Post`، ما باید`()PostForm` را فراخوانی کنیم و آن را به تمپلیت منتقل کنیم. ما به این *view* باز خواهیم گشت، اما در حال حاضر، بیایید به سرعت یک تمپلیت برای این فرم ایجاد کنیم. + +## تمپلیت + +لازم است یک فایل به نام `post_edit.html`در پوشه `blog/templates/blog`بسازیم و آن را در ویرایشگر کد بازکنیم. برای آنکه یک فرم کار کند به چند چیز نیاز داریم: + +* ما باید فرم را نمایش دهیم. مثلاً می‌توانیم این کار را با {% raw %}`{{ form.as_p }}`{% endraw %} انجام دهیم. +* خط بالا باید درون تگ فرم HTML پیچیده شود: `... `. +* ما به یک دکمه `ذخیره کردن` نیاز داریم. این کار را با یک دکمه HTML انجام می‌دهیم: ``. +* و در نهایت، درست بعد از باز شدن تگ `
` باید {% raw %}`{% csrf_token %}`{% endraw %} را اضافه کنیم. نوشتن این عبارت بسیار مهم است، زیرا فرم‌های شما را امن می‌کند! اگر شما این تکه را فراموش کنید، جنگو هنگام تلاش برای ذخیره کردن فرم پیغام خطا می‌دهد: + +![صفحه خطا CSRF](images/csrf2.png) + +خوب، بگذار ببینیم HTML در فایل `post_edit.html` چطور باید باشد: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +حالا زمان به روزرسانی پروژه است! بله فرم شما نمایش داده می‌شود! + +![فرم جدید](images/new_form2.png) + +اما یک دقیقه صبر کنید وقتی چیزی را در فیلدهای `title` و `text` تایپ کنید و سعی کنید آن را ذخیره کنید، چه اتفاقی خواهد افتاد؟ + +هیچ چی! ما یک بار دیگر در همان صفحه هستیم و متن ما رفته است... و هیچ پست جدیدی اضافه نشده است. پس چه اتفاقی افتاد؟ + +جواب این است: هیچ چیز. ما باید در *view* خودمان کمی کارهای بیشتری انجام دهیم. + +## ذخیره فرم + +یکبار دیگر فایل `blog/views.py` را در ویرایشگر کد باز کنید. در حال حاضر آنچه که در ویو `post_new` داریم این هاست: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +هنگامی که فرم را ارسال می‌کنیم، ما به همان ویوی قبل باز می‌گردیم، اما این بار ما در `request` داده‌های بیشتری داریم، به ویژه در `request.POST` (نامگذاری request.POST هیچ ارتباطی با "پست" وبلاگ ندارد و به معنی آن است که ما در حال ارسال اطلاعات هستیم). به یاد می آورید که چگونه در فایل HTML، تعریف `
` دارای متغیر `method="POST"` بود؟ تمام فیلدهای فرم اکنون در `request.POST` قرار دارند. شما نباید عبارت `POST` را در اینجا به چیز دیگری تغییر دهید (تنها مقدار معتبر دیگر برای `method` مقدار `GET` است، اما الان وقت آن را نداریم تا تفاوت آن‌ها را توضیح دهیم). + +بنابراین در *view*، ما دو موقعیت جداگانه برای رسیدگی داریم: اول اینکه زمانی که ما برای اولین بار به صفحه می‌رویم و یک فرم خالی را می‌خواهیم، و دوم، وقتی با اطلاعات نوشته شده درون فرم، به *view* برمی‌گردیم. بنابراین ما نیاز به اضافه کردن یک شرط داریم (ما از `if`برای این منظور استفاده می‌کنیم): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +وقت آن است که نقاط `[...]` را پر کنید. اگر مقدار `method` برابر با `POST` باشد، ما می خواهیم که با اطلاعات درون فرم `PostForm` را بسازیم، درست است؟ ما این کار را به صورت زیر انجام خواهیم داد: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +قدم بعدی این است که بررسی کنید که آیا فرم صحیح است (تمام فیلدهای لازم تنظیم شده و مقادیر نادرست وارد نشده است). ما این کار را با `form.is_valid()` انجام می‌دهیم. + +ما بررسی می کنیم که آیا فرم معتبر است و اگر چنین باشد، می توانیم آن را ذخیره کنیم! + +{% filename %}blog/views.py{% endfilename %} + +```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` که هم اکنون ساخته‌ایم برویم، درست است؟ برای این کار ما نیاز به فراخوانی دیگری داریم: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +آن را در ابتدای فایل خود اضافه کنید. و اکنون می‌توان گفت، "به صفحه جزییات پست `post_detail` برای پست جدید برو": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` نام ویویی است که ما می‌خواهیم به آن برویم. به یاد دارید که این *view* نیاز به متغیر `pk` دارد؟ برای فرستادن آن به ویو، از `pk=post.pk` استفاده می‌کنیم، که در آن `post` جدیدترین پست وبلاگ است! + +خوب، ما خیلی صحبت کرده‌ایم، اما احتمالاً می‌خواهید ببینید که کل *view* چگونه به نظر می‌رسد، درست است؟ + +{% filename %}blog/views.py{% endfilename %} + +```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` هدایت می‌شویم! + +ممکن است متوجه شده باشید که قبل از ذخیره پست، تاریخ انتشار را تنظیم کرده‌ایم. بعدها، ما دکمه *publish button* را در بخش **Django Girls Tutorial: Extensions** معرفی می‌کنیم. + +این عالیه! + +> همانطور که اخیراً رابط کاربری ادمین جنگجو را استفاده کردیم، سیستم در حال حاضر فکر می‌کند ما هنوز در سیستم لاگین هستیم. چند موقعیت وجود دارد که می تواند منجر به خروج ما از رابط کاربری مدیریت شود (بسته شدن مرورگر، راه اندازی مجدد دیتابیس و غیره). اگر در هنگام ایجاد یک پست متوجه شدید که خطایی در رابطه با عدم وجود یک کاربر ایجاد شده است، به صفحه مدیریت http://127.0.0.1:8000/admin بروید و دوباره وارد شوید. این مسأله به طور موقت حل خواهد شد. یک تکلیف اضافه برای خانه که بعد از بخش اصلی آموزش، انتظار شما را می‌کشد رفع مشکلات امنیتی وبسایت در بخش **Homework: add security to your website!** است. + +![خطا ورود به سیستم](images/post_create_error.png) + +## اعتبارسنجی فرم + +حالا به شما نشان می‌دهیم که فرم‌ها در جنگو چقدر جالب هستند. یک پست وبلاگ باید فیلدهای `title` و `text` را داشته باشد. در مدل `Post` ما نگفتیم که این فیلدها (به غیر از `published_date`) الزامی نیستند، بنابراین، جنگو به طور پیش فرض آن‌ها را الزامی می‌داند. + +سعی کنید فرم را بدون `title` و `text` ذخیره کنید. حدس بزنید چه اتفاقی خواهد افتاد! + +![اعتبارسنجی فرم](images/form_validation2.png) + +جنگو مواظب است که تمام فیلدهای موجود در فرم ما صحیح پر شده باشند. فوق‌العاده نیست؟ + +## ويرايش فرم + +حالا ما می‌دانیم که چگونه یک پست جدید اضافه کنیم. اما اگر بخواهیم یک فرم موجود را ویرایش کنیم، چه؟ این کار بسیار شبیه آنچه ما انجام داده‌یم است. بگذارید برخی از چیزهای مهم را سریع بسازیم. (اگر چیزی را درک نمی‌کنید، باید از مربی خود بپرسید یا در فصل‌های قبلی نگاه کنید، زیرا ما قبلاً همه این مراحل را پوشش دادیم.) + +ابتدا، اجازه دهید که آیکونی که نمایش دهنده دکمه اصلاح است را ذخیره کنیم. فایل [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) را دانلود کنید و آن را در آدرس `blog/templates/blog/icons/` ذخیره کنید. + +فایل `blog/templates/blog/post_detail.html` را در ویرایشگر متن باز کنید و خطوط زیر را به عنصر `article` اضافه کنید: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +قالب فوق شبیه به این خواهد شد: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +فایل `blog/urls.py` را باز کنید و خط زیر را به آن اضافه کنید: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +ما از این تمپلیت `blog/templates/blog/post_edit.html` مجدداً استفاده خواهیم کرد پس تنها قطعه باقی مانده *view* است. + +فایل `blog/views.py` را باز کنید و خط زیر را به انتهای این فایل اضافه کنید: + +{% filename %}blog/views.py{% endfilename %} + +```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` اضافی از `urls` ارسال کرده‌ایم. سپس مدل `Post` را که می‌خواهیم اصلاح کنیم با دستور `get_object_or_404(Post, pk=pk)` می‌گیریم و بعد از آن یک فرم می‌سازیم و این فرم را به صورت `instance`ارسال می‌کنیم، هر دو این کارها وقتی اتفاق می‌افتد که فرم را ذخیره می‌کنیم… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +… و هنگامی که یک فرم را به این صورت برای تغییر دادن باز می‌کنیم: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +بسیار خوب، حالا بیایید امتحان کنیم که آیا کار می‌کند! به صفحه `post_detail` بروید. باید یک کلید edit در گوشه سمت راست بالا باشد: + +![کلید Edit](images/edit_button2.png) + +وقتی بر روی آن کلیک کنید یک فرم که با اطلاعات پست وبلاگی ما پر شده است نشان داده می‌شود: + +![فرم Edit](images/edit_form2.png) + +به راحتی محتوای پست را تغییر دهید و آن را ذخیره کنید! + +تبریک! برنامه شما کامل و کامل‌تر می‌شود! + +اگر اطلاعات بیشتری در مورد فرم‌ها در جنگو لازم دارید باید مستندات مربوط به آن را در این آدرس بخوانید: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## امنیت + +ساختن یک پست جدید فقط با یک کلیک، بسیار فوق العاده است! اما همین الان هرکسی که از صفحه شما بازدید می‌کند می‌تواند به راحتی یک پست جدید بسازد و این احتمالاً چیزی نیست که شما بخواهید. حالا بیایید کاری کنیم که این دکمه فقط برای شما نشان داده شود و کس دیگری آن را نبیند. + +فایل `blog/templates/blog/base.html` را در ویرایشگر کد باز کنید بخش `div` با نام `header` و تگ a موجود در آن را پیدا کنید. باید چیزی شبیه به این باشد: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +حالا ما می‌خواهیم یک تگ `{% if %}` دیگر به این اضافه کنیم که باعث خواهد شد این لینک فقط برای کاربری نشان داده شود که به عنوان ادمین وارد شده باشد که در حال حاضر فقط شما هستید! تگ `` را به شکل زیر تغییر دهید: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +تگ `{% if %}` باعث خواهد شد که لینک فقط در صورتی به مرورگر ارسال شود که کاربر درخواست کننده صفحه، با حساب کاربری ادمین وارد شده باشد. این کار به طور کامل ساختن پست جدید را محافظت نمی‌کند اما قدم اولیه‌ی خوبی است. مباحث بیشتری از امنیت را در بخش‌های اضافه آموزش پوشش خواهیم داد. + +کلید edit را که به صفحه جزییات یک پست اضافه کردیم به یاد دارید؟ حالا همین کار را برای آن صفحه نیز می‌خواهیم انجام دهیم تا دیگران قادر به تغییر محتوای یک پست نباشند. + +فایل `blog/templates/blog/post_detail.html` را باز کنید و خط زیر را پیدا کنید: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +آن را به شکل زیر تغییر دهید: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +از آنجا که احتمالاً هنوز به عنوان ادمین در سیستم لاگین کرده‌اید، اگر صفحه را دوباره بازخوانی کنید، تغییر خاصی را نمی‌بینید. صفحه را در یک مرورگر دیگر یا یک پنجره ناشناس incognito window (در Windows Edge به آن "InPrivate" می‌گویند) بارگذاری کنید. خواهید دید که لینک و آیکون اصلاح پست، نمایش داده نمی‌شود! + +## یک چیز دیگر: زمان دیپلوی است! + +بیایید ببینیم آیا همه این تغییرات در PythonAnywhere کار می‌کند. وقت یک دیپلوی کردن دیگر است! + +* ابتدا کد جدید را کامیت کنید و آن را به GitHub بفرستید: + +{% filename %}خط فرمان{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* سپس در کنسول [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/) تایپ کنید: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(یادتان باشد که `` را با زیر دامنه اصلی خود در PythonAnywhere عوض کنید البته بدون آکولادها.) + +* در نهایت به صفحه ["Web" page](https://www.pythonanywhere.com/web_app_setup/) بروید (از کلید منو در بالا و سمت راست کنسول استفاده کنید) و کلید **Reload** را بزنید. آدرس وبلاگ خودتان https://subdomain.pythonanywhere.com را باز کنید تا تغییرات را ببینید. + +به نتیجه رسید! تبریک! :) \ No newline at end of file diff --git a/fa-IR/django_installation/README.md b/fa-IR/django_installation/README.md new file mode 100644 index 00000000000..dc3cccdfa7d --- /dev/null +++ b/fa-IR/django_installation/README.md @@ -0,0 +1,7 @@ +# نصب و راه اندازی جنگو + +> **نکته** اگر از Chromebook استفاده می‌کنید، این فصل را رد کنید و مطمئن شوید که دستورالعمل [ تنظیمات Chromebook](../chromebook_setup/README.md) را دنبال کنید. +> +> **نکته** اگر مراحل [نصب و راه‌اندازی](../installation/README.md) را انجام داده‌اید یعنی این بخش انجام شده است، می‌توانید مستقیم به بخش بعد بروید! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/fa-IR/django_installation/instructions.md b/fa-IR/django_installation/instructions.md new file mode 100644 index 00000000000..b15dae2cd65 --- /dev/null +++ b/fa-IR/django_installation/instructions.md @@ -0,0 +1,229 @@ +> قسمت‌هایی از این بخش بر اساس دوره آموزشی 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 متعلق به Markus Zapke-Gründemann و همکاران می‌باشد. + +## محیط مجازی + +قبل از اینکه ما جنگو را نصب کنیم، ابزاری بسیار پراستفاده به شما می‌دهیم تا با نصب آن محیط برنامه نویسی خود را بر روی کامپیوترتان تمیز و مرتب نگه دارید. می‌توانید برای ادامه کار از این مرحله صرف نظر کنید اما استفاده از آن بسیار توصیه می‌شود. شروع کار با تنظیمات مناسب جلوی بسیاری از مشکلات در آینده را می‌گیرد! + +بنابراین، اجازه دهید یک ** محیط مجازی ** یا virtual environment بسازیم (همچنین به آن * virtualenv* هم گفته می‌شود). محیط مجازی، تنظیمات پایتون/جنگو را برای هر پروژه و جدا از دیگر پروژه‌ها، قرنطینه و حفظ خواهد کرد. یعنی هر تغییری که در تنظیمات یک وبسایت انجام می‌دهید، بر روی دیگر وبسایت‌هایی که در حال توسعه آن‌ها هستید تاثیر نخواهد گذاشت. تمیز و مرتب، اینطور نیست؟ + +آنچه شما باید انجام دهید این است که یک پوشه را پیدا کنید که در آن می‌خواهید ` محیط مجازی` را ایجاد کنید. برای مثال، پوشه home. در ویندوز، چیزی شبیه `C:\Users\Name` است (که در آن `Name` نام کاربری شما است که با آن وارد ویندوز شده‌اید). + +> **نکته: ** در ویندوز اطمینان حاصل کنید که نام این پوشه حاوی کاراکترهای خاص یا دارای اعراب نیست؛ اگر نام کاربری شما دارای کاراکترهای خاص است، از یک پوشه دیگر استفاده کنید، به عنوان مثال `C:\djangogirls`. + +برای این آموزش ما از یک پوشه جدید `djangogirls` در پوشه اصلی شما استفاده خواهیم کرد: + +{% filename %}خط فرمان{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +ما یک محیط مجازی به نام `myvenv` خواهیم ساخت. فرمان کلی در این قالب خواهد بود: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 -m venv myvenv + + + + +برای ایجاد یک `محیط مجازی` جدید، باید کنسول خط فرمان را باز کنید و دستور <`python -m venv myvenv` را اجرا کنید. شبیه این خواهد شد: + +{% filename %}خط فرمان{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +در اینجا `myvenv` نام `محیط مجازی` شماست. می‌توانید هر نام دیگری انتخاب کنید اما از حروف کوچک استفاده کنید و از اسپیس، اعراب گذاری و کاراکترهای خاص استفاده نکنید. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +می‌توانیم با دستور `python3 -m venv myvenv` هم در لینوکس و هم در OS X `محیط مجازی` بسازیم. شبیه این خواهد بود: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 -m venv myvenv + + +نام `محیط مجازی` شما، `myvenv` است. می‌توانید هر نام دیگری انتخاب کنید اما از حروف کوچک استفاده کنید و از اسپیس استفاده نکنید. همچنین بهتر است اسم کوتاهی انتخاب کنید چون بعدتر ارجاعات زیادی به آن خواهید داشت! + +> **نکته: ** در بعضی نسخه‌های دبیان/اوبونتو ممکن است چنین پیغام خطایی دریافت کنید: +> +> {% filename %}خط فرمان{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> در این موارد دستورالعمل داده شده در بالا را دنبال کنید. پکیج `python3-venv` را نصب کنید: {% filename %}خط فرمان{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **نکته: ** در بعضی نسخه‌های دبیان/اوبونتو ساختن محیط مجازی با این دستور ممکن است باعث چنین خطایی بشود: +> +> {% filename %}خط فرمان{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> برای حل این مشکل، از دستور `virtualenv` استفاده کنید. +> +> {% filename %}خط فرمان{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **نکته: ** اگر چنین خطایی گرفتید +> +> {% filename %}خط فرمان{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> در عوض از این دستور استفاده کنید: +> +> {% filename %}خط فرمان{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## کار کردن با محیط مجازی + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +محیط مجازی خود را با اجرای دستور زیر فعال کنید: + +{% filename %}خط فرمان{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. در این شرایط یک بار دیگر Windows PowerShell را با گزینه "Run as Administrator" اجرا کنید. سپس دستورات زیر را قبل از فعال کردن محیط مجازی خود، اجرا کنید: +> +> {% filename %}خط فرمان{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> مزیت آن این است که لازم نیست بین پنجره ویرایشگر کد و پنجره خط فرمان جابجا شوید + + + + + +محیط مجازی خود را با اجرای دستور زیر فعال کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ source myvenv/bin/activate + + +به یاد داشته باشید که `myvenv` را با نامی که برای `محیط مجازی` خود انتخاب کرده‌اید عوض کنید! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}خط فرمان{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +هنگامی که پیشوند `(myvenv)` در کنسول خط فرمان اضافه شود به معنی آن است که `محیط مجازی` شما فعال شده است. + +وقتی درون یک محیط مجازی کار می‌کنید کلمه `python` به صورت اتوماتیک به نسخه صحیح پایتون ارجاع می‌دهد در نتیجه می‌توانید به جای `python3` از `python` استفاده کنید. + +بسیار خوب، ما همه نیازمندی‌ها را داریم حالا می‌توانیم جنگو را نصب کنیم! + +## نصب جنگو {#django} + +حالا که `محیط مجازی` شما فعال شده است می‌توانید جنگو را نصب کنید. + +قبل از آن باید مطمئن شویم که آخرین نسخه `pip` که برای نصب جنگو استفاده می‌شود را داریم: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### نصب پکیج‌ها و پیش‌نیازهایشان + +یک فایل پیش‌نیازها شامل لیستی از پکیج‌های وابسته است که باید به کمک `pip install` نصب شوند: + +در ابتدا یک فایل `requirements.txt` در پوشه `djangogirls/` بسازید. معمولاً می‌توانید از خود ویرایشگر کد که قبل‌تر نصب کرده‌اید هم برای ساختن فایل جدید استفاده کنید. یک فایل جدید در ویرایشگر کد بسازید و سپس به نام `requirements.txt`در پوشه `djangogirls/` ذخیره‌اش کنید. پوشه شما شبیه این خواهد بود: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +در فایل `djangogirls/requirements.txt` باید خط زیر را اضافه کنید: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +حالا دستور `pip install -r requirements.txt` را اجرا کنید تا جنگو نصب شود. + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). اگر چنین است لطفاً از مسیری استفاده کنید که در آن اسپیس به کار نرفته باشد (مثلا چنین مسیری `C:\djangogirls`). یک محیط مجازی در پوشه جدید درست کنید سپس محیط مجازی قبلی را پاک کنید و دستور بالا را دوباره اجرا کنید. (جابجا کردن پوشه مربوط به محیط مجازی ایده خوبی نیست و باعث می‌شود محیط مجازی کار نکند. محیط مجازی با آدرس مطلق کار می‌کند) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}خط فرمان{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> اگر هنگام اجرای دستور pip بر روی اوبونتو نسخه 12.04 پیغام خطا گرفتید از دستور `python -m pip install -U --force-reinstall pip` برای اصلاح پکیج pip در محیط مجازی استفاده کنید. + + + +عالی! بالاخره در نهایت آماده شدید تا یک برنامه جنگو بسازید! \ No newline at end of file diff --git a/fa-IR/django_models/README.md b/fa-IR/django_models/README.md new file mode 100644 index 00000000000..34822e580fd --- /dev/null +++ b/fa-IR/django_models/README.md @@ -0,0 +1,202 @@ +# مدل در جنگو + +آنچه الان می‌خواهیم بسازیم چیزی است که تمام پست‌های ما در وبلاگ را ذخیره می‌کند. اما برای اینکه بتوانیم این کار را بکنیم باید کمی در مورد مفهوم `شیء` صحبت کنیم. + +## اشیاء + +مفهومی در برنامه نویسی وجود دارد که به آن `برنامه‌نویسی شیء‌گرا` گفته می‌شود. به این معنی که به جای آنکه همه چیز را در ردیف‌هایی طولانی از دستورات بنویسیم می‌توانیم مدل هایی درست کنیم و تعریف کنیم که این مدل ها چگونه با هم ارتباط داشته باشند. + +یک شیء چیست؟ یک شیء مجموعه‌ای از خصوصیات و اعمال است. ممکن است کمی عجیب باشد اما برای شما مثالی خواهیم زد. + +اگر بخواهیم مدلی برای یک گربه بسازیم یک شیء به نام `Cat` میسازیم که دارای خصوصیاتی است مانند `رنگ`، `سن`، `حالت` (مثلاً خوب، بد یا خواب‌آلود) و `مالک` (که می‌تواند اشاره به یک شیء `Person` یا در در مورد گربه‌های ولگرد، بدون اشاره به فردی خاص، خالی بماند). + +یک شیء از نوع `Cat` دارای فعالیتی‌هایی مانند: `خُرخُر کردن`، `خراشیدن` و یا `غذا خوردن` است. (برخی مواقع به گربه، `غذای گربه` می‌‌دهیم که می‌تواند یک شیء جداگانه باشد که خصوصیت `مزه` داشته باشد). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +بنابراین ایده اصلی آن است که چیزهای واقعی در کدها با خصوصیات (که به آن `object properties` می‌گوییم) و اعمال (که به آن `methods` می‌گوییم) تعریف شوند. + +ما می‌خواهیم یک وبلاگ درست کنیم، درست است؟ چگونه یک مدل برای پست‌های وبلاگی بسازیم؟ + +باید به این سوال پاسخ دهیم که: یک پست وبلاگی چیست؟ چه خصوصیاتی دارد؟ + +خب، پست وبلاگی ما قطعاً به مقداری متن و یک عنوان نیاز دارد، درست است؟ بسیار خوب خواهد بود که بدانیم چه کسی مطلب را نوشته است، پس به نویسنده هم احتیاج داریم. سرانجام می‌خواهیم بدانیم که این مطلب در چه تاریخی نوشته و منتشر شده است. + + Post + -------- + title + text + author + created_date + published_date + + +چه کارهایی با یک پست وبلاگی می‌توان انجام داد؟ بسیار جالب خواهد بود که `متدهایی` داشته باشیم که بتواند یک پست را منتشر کند. چطور است؟ + +بنابراین به یک متد انتشار یا `publish` نیاز داریم. + +حالا که می‌دانیم دقیقاً به چه چیزی احتیاج داریم بیایید مدل سازی در جنگو را شروع کنیم! + +## مدل در جنگو + +حالا که می‌دانیم شیء چیست، می‌توانیم یک مدل جنگویی برای پست‌های وبلاگ‌مان بسازیم. + +یک مدل در جنگو نوعی شیء ویژه است که در `پایگاه داده` یا database ذخیره می‌شود. یک پایگاه داده مجموعه‌ای از اطلاعات است. جایی است که در آن اطلاعات مربوط به کاربرها، پست‌های وبلاگی و غیره را نگهداری می‌کنیم. ما از پایگاه داده SQLite برای ذخیره اطلاعات استفاده می‌کنیم. این پایگاه داده، پایگاه داده پیشفرض در جنگو است و الان برای ما کافی است. + +شما می‌توانید یک مدل را در پایگاه داده، چیزی شبیه به یک صفحه گسترده با ستون‌ها (فیلدها) و ردیف‌ها(داده‌ها) تصور کنید. + +### ساختن یک اپلیکیشن + +برای آنکه همه چیز مرتب باشد ما یک برنامه مجزا (اپلیکیشن) در پروژه خود خواهیم ساخت. خوب است که همه چیز از ابتدا مرتب باشد. برای ساخت یک برنامه جدید باید دستور زیر را در خط فرمان اجرا کنیم (در پوشه `djangogirls` و جایی که فایل `manage.py` وجود دارد): + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +خواهید دید که یک پوشه جدید به نام `blog` ساخته شده و شامل تعدادی فایل است. پوشه‌ها و فایل‌ها در پروژه ما باید شبیه به این باشد: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +بعد از ساختن این برنامه، باید به جنگو بگوییم تا از آن استفاده کند. این کار را در فایل `mysite/settings.py` انجام می‌دهیم -- این فایل را در ویرایشگر کد باز کنید. باید `INSTALLED_APPS` را پیدا کنیم و دقیقاً بالای علامت `[` در انتهای این بخش، خطی شامل `'blog.apps.BlogConfig',` را اضافه کنیم. پس در نهایت شبیه این خواهد بود: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### ساختن مدل برای پست وبلاگ + +در فایل `blog/models.py` ما تمام اشیائی را که به آن `مدل Model` می‌گوییم تعریف می‌کنیم. اینجا فضایی است که پست‌های وبلاگی را تعریف می‌کنیم. + +فایل `blog/models.py` را در ویرایشگر کد باز کنید، تمام محتویات آن را پاک کنید و کد‌های زیر را در آن بنویسید: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User', on_delete=models.CASCADE) + 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" هم می‌گویند که مخفف "double-underscore" است. + +عجیب به نظر می‌رسد؟ نگران نباشید ما درباره عملکرد این خط ها توضیح خواهیم داد! + +تمام خطوطی که با `from` یا `import` شروع می‌شوند خطوطی هستند که محتوایی را از یک فایل دیگر به این فایل اضافه می‌کنند. پس به جای آنکه یک محتوای یکسان را در هر فایل تکرار کنیم، می‌توانیم از این الگو استفاده کنیم `from ... import ... `. + +`class Post(models.Model):` – این خط مدل ما را تعریف می‌کند (که یک `شیء` یا object است). + +- `class` کلید واژه‌ای است که نشان می‌دهد در حال تعریف کردن یک شیء هستیم. +- `Post` نام مدل ما است. می‌توانیم به آن نام متفاوتی بدهیم (اما نباید از کاراکترهای خاص و اسپیس استفاده کنیم). همیشه نام یک کلاس را با حروف بزرگ شروع کنید. +- `models.Model` به این معنی است که Post یک مدل جنگویی است، بنابراین جنگو می‌داند که این مدل باید در پایگاه داده ذخیره شود. + +حالا ویژگی‌هایی که در مورد آن‌ها صحبت کردیم را اضافه می‌کنیم: `title`، `text`، `created_date`، `published_date` و `author`. برای این کار باید ویژگی‌های هرکدام از این‌ها را مشخص کنیم (آیا متن است؟ یا عدد؟ یا تاریخ؟ یا ارتباطی با یک شیء دیگر دارد، مثلا کاربر؟) + +- `models.CharField` – این عبارت مشخص می‌کند که ویژگی مورد نظر از جنس متن با تعداد کاراکتر محدود است. +- `models.TextField` – این عبارت برای اختصاص دادن متن با تعداد کاراکتر نامحدود است. به نظر برای متن پست‌های وبلاگی مناسب است، درست است؟ +- `models.DateTimeField` – مشخص کننده تاریخ و زمان است. +- `models.ForeignKey` – نشان دهنده ارتباط به یک مدل دیگر است. + +ما همه قطعات کد را توضیح نخواهیم داد برای آنکه زمان بسیار زیادی می‌گیرد. اگر بخواهید اطلاعات بیشتری در مورد فیلدهای یک مدل‌ و انواع آن بدانید باید نگاهی به مستندات جنگو بیندازید (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +منظور از `def publish(self):` چیست؟ این دقیقاً متد یا عملیات `publish` (انتشار یک پست وبلاگی) است که قبل‌تر در مورد آن صحبت کردیم. عبارت `def` نشان دهنده آن است که یک تابع یا متد تعریف شده‌ است و `publish` نام این تابع است. شما می‌توانید نام این تابع را به دلخواه عوض کنید. برای نامگذاری متدها، معمولاً از حروف کوچک و خط زیرین (underscore) به جای کاراکتر فاصله (space) استفاده می‌کنیم. برای مثال، تابعی که برای محاسبه قیمت متوسط لازم داریم به این صورت نامگذاری می‌شود `calculate_average_price`. + +توابع معمولاً یک مقدار را باز می‌گردانند که با `return` تعریف می‌شود. نمونه‌ای از این بازگرداندن در تابع `__str__` وجود دارد. در این سناریو وقتی ما تابع `__str__()` را فراخوانی می‌کنیم یک نوشته (با فرمت **string**) که حاوی عنوان پست وبلاگی است دریافت می‌کنیم. + +همچنین توجه داشته باشید که هر دو تابع `def publish(self):` و `def __str__(self):` به کمک فاصله‌گذاری ابتدای خط، درون کلاس تعریف شده‌اند. چون پایتون به فاصله‌ها حساس است نیاز داریم که میزان فاصله ابتدا خط برای متدها درست تعریف شوند تا متد، درون کلاس قرار داشته باشد. در غیر اینصورت متدها عضوی از کلاس نخواهند بود، و ممکن است رفتار غیرمنتظره‌ای ببینید. + +اگر هنوز چیزی در مورد مدل‌ها برای شما مبهم است حتماً از مربی خود بپرسید! می‌دانیم که یادگرفتن مفاهیم اشیاء و توابع به طور همزمان، پیچیده است. ولی حداقل الان کمی برای شما واضح‌تر شده است! + +### ساختن جدول برای مدل‌ها در پایگاه داده‌ها + +آخرین مرحله این است که مدل جدیدی که ساخته‌ایم را به پایگاه داده اضافه کنیم. ابتدا باید جنگو را از تغییراتی که در مدل‌ها ایجاد کرده‌ایم آگاه کنیم. (این تغییرات همین کارهایی است که انجام داده‌ایم!) به کنسول خط فرمان بروید و تایپ کنید `python manage.py makemigrations blog`. چیزی شبیه این خواهید دید: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**نکته: **به یاد داشته باشید که فایل‌هایی که تغییر داده‌اید را ذخیره کنید وگرنه ممکن است کامپیوتر نسخه قبلی فایل را در نظر بگیرد و پیغام خطا نشان بدهد. + +جنگو یک فایل مهاجرت یا migration برای ما درست می‌کند که ما باید آن را به پایگاه داده ارسال کنیم. عبارت `python manage.py migrate blog` را اجرا کنید و خروجی باید شبیه به این باشد: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +هورا! مدل Post ما اکنون در پایگاه داده قرار گرفته است! جالب خواهد بود که نگاهی به آن بیندازیم! پس به سراغ بخش بعدی بروید تا ببینید Post ها به چه صورتی درآمده‌اند! \ No newline at end of file diff --git a/fa-IR/django_orm/README.md b/fa-IR/django_orm/README.md new file mode 100644 index 00000000000..653a5e0371f --- /dev/null +++ b/fa-IR/django_orm/README.md @@ -0,0 +1,221 @@ +# ORM و QuerySets در جنگو + +در این فصل شما نحوه اتصال جنگو به پایگاه داده و روش ذخیره اطلاعات در آن را یاد خواهید گرفت. بگذارید شروع کنیم! + +## QuerySet چیست؟ + +به صورت خلاصه، کوئری‌ست لیستی از تعدادی شیء مربوط به یک مدل خاص است. کوئری‌ست به شما این امکان را می‌دهد که داده‌ها را از پایگاه داده بخوانید، فیلتر کنید یا آن‌ها را مرتب کنید. + +ساده‌ترین راه فهمیدن آن، مثال است. پس شروع می‌کنیم.آماده‌اید؟ + +## کنسول خط فرمان جنگو + +کنسول‌های لوکال خود را باز کرده (نه در PythonAnywhere) و این دستور را تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + + +باید پاسخی مانند زیر دریافت کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +شما در حال حاضر در کنسول تعاملی جنگو هستید. این محل کاملاً شبیه به محیط تعاملی پایتون می‌باشد با این تفاوت که چند ویژگی جادویی جنگو را در بر دارد. :) شما می‌توانید تمامی دستورات پایتون را در اینجا استفاده کنید. + +### تمام اشیاء + +در ابتدا تمامی پست ها را نمایش می دهیم. با دستور زیر می توان این کار را انجام داد: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +اوه اوه! به خطا خوردیم. این خطا به این معنی است که هیچ پستی وجود ندارد. درست است! فراموش کردیم که پست ها را import کنیم! + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> from blog.models import Post +``` + +مدل `Post` را از `blog.models` فراخوانی می‌کنیم. حالا دوباره تمامی پست‌ها را نمایش می‌دهیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +لیستی از پست‌هایی که قبلا ایجاد کرده بودیم درست شد! ما این پست‌ها را با استفاده از صفحه مدیریت جنگو ایجاد کرده‌بودیم. اما حالا می‌خواهیم پست جدیدی با استفاده از پایتون درست کنیم. چطور این کار را انجام می‌دهیم؟ + +### ساختن شیء + +به صورت زیر می‌توان یک شیء جدید از نوع Post در پایگاه داده ایجاد کرد: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +اما ما در اینجا یک عنصر گم شده داریم: `نویسنده`. نیاز هست که یک نمونه از مدل `User` را به عنوان نویسنده برای ساخت شیء جدید تعریف کنیم. نحوه انجام کار به صورت زیر می باشد. + +بیایید اول مدل User را فراخوانی کنیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +چه کاربرانی در پایگاه داده داریم؟ این را امتحان کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +این همان کاربر اصلی یا superuser است که کمی قبل‌تر ساخته‌ایم! حالا بیایید نمونه ای از روی کاربر اصلی بسازیم (این خط را مطابق نام کاربر اصلی که قبلاً وارد کرده‌اید تغییر دهید): + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +همان طور که می‌بینید ما یک `کاربر` را به کمک دستور `get` و با ارجاع دادن مقدار 'ola' به متغیر `username` فراخوانی کردیم. خیلی دقیق! + +الان ما می‌توانیم پست خود را ایجاد کنیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +هورا! می‌خواهید امتحان کنیم که آیا درست کار می‌کند؟ + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +بنابراین یک پست دیگر در لیست خواهیم داشت! + +### اضافه کردن پست های بیشتر + +حالا برای تفریح هم که شده می‌توانید پست‌های بیشتری بسازید تا با نحوه کارکرد آن بهتر آشنا شوید. دو یا سه پست دیگربسازید و سپس به مرحله بعد بروید. + +### فیلتر کردن اشیاء + +بخش مهمی از QuerySet، توانایی فیلتر کردن آن است. در اینجا می‌خواهیم تمام پست‌هایی که کاربر ola ساخته است را پیدا کنیم. در اینجا از عبارت `filter` به جای `all` در `Post.objects.all()` استفاده می‌کنیم. در پرانتز ما شرطی (شرایطی) که لازم است وجود داشته باشد تا شیء مورد نظر به QuerySet اضافه شود را بیان می‌کنیم. در اینجا، شرط ما این است که `author` برابر با `me` باشد. نحوه نوشتن آن در جنگو به این صورت است `author=me`. الان یک کد به صورت زیر داریم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +یا شاید ما بخواهیم تمام پست‌هایی که در فیلد `title` کلمه 'title' را داشته باشند پیدا کنیم؟ + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **نکته** دقت کنید که ۲تا کاراکتر underscore ( `ـ`) در میان `title` و `contains` وجود دارد. ORM جنگو از این قانون استفاده می‌کند تا عملیات یا فیلتر مورد نظر را ("contains") از نام فیلد ("title") جدا کند. اگر فقط از یک underscore استفاده کنید خطایی مانند این دریافت خواهید کرد "FieldError: Cannot resolve keyword title_contains". + +همچنین می‌توانید لیستی از تمام پست‌های منتشر شده دریافت کنید. ما این کار را با فیلتر کردن همه پست‌هایی که برای آن‌ها `published_date` تعیین کرده بودیم انجام می‌دهیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +متاسفانه پست هایی که از طریق کنسول پایتون اضافه کرده‌ایم هنوز منتشر نشده‌اند. اما می‌توانیم این وضعیت را تغییر دهیم! ابتدا یک نسخه از پست‌هایی که می‌خواهیم منتشر کنیم تهیه می‌کنیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +و حالا با متد `publish` آن را منتشر می کنیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> post.publish() +``` + +الان دوباره سعی کنید لیستی از پست‌های منتشر شده را نمایش دهید (دکمه جهت بالا در کیبورد را ۳ بار زده و `enter` کنید): + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### مرتب‌سازی اشیاء (Ordering objects) + +QuerySet ها همچنین به شما اجازه می‌دهند لیستی از اشیاء را مرتب کنید. بیایید آن‌ها را بر اساس `created_date`، مرتب کنیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +همچنین با اضافه کردن `-` در ابتدای دستور می‌توانیم اشیاء را به صورت معکوس مرتب کنیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### کوئری‌های پیچیده از طریق زنجیره توابع + +همانطور که دیدید برخی از توابع در `Post.objects`، یک کوئری ست باز می‌گردانند. همان تابع می‌تواند مجدداً بر روی یک کوئری ست اعمال شود و کوئری ست دیگری برگرداند. بنابراین، شما می‌توانید تاثیر آن‌ها را به صورت **زنجیره‌ای** با هم ترکیب کنید: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +این روش واقعاً قدرتمند است و به شما اجازه می‌دهد کوئری‌های پیچیده‌ای بسازید. + +موفق شدیم! شما الان برای قسمت بعدی آماده هستید. برای بستن پوسته (shell) دستور زیر را تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> exit() +``` \ No newline at end of file diff --git a/fa-IR/django_start_project/README.md b/fa-IR/django_start_project/README.md new file mode 100644 index 00000000000..4d1846b5290 --- /dev/null +++ b/fa-IR/django_start_project/README.md @@ -0,0 +1,260 @@ +# اولین پروژه جنگو شما! + +> قسمت‌هایی از این بخش بر اساس دوره آموزشی Geek Girls Carrots بنا شده است (https://github.com/ggcarrots/django-carrots). +> +> قسمت‌هایی هم بر اساس دوره آموزشی [django-marcador tutorial](http://django-marcador.keimlink.de/) تحت مجوز بین المللی Creative Commons Attribution-ShareAlike 4.0 تهیه شده است. امتیاز دوره آموزشی django-marcador متعلق به Markus Zapke-Gründemann و همکاران است. + +قصد داریم یک وبلاگ کوچک بسازیم! + +در قدم اول یک پروژه جدید جنگو میسازیم. در واقع ساختن یک پروژه جنگو شامل اجرا کردن دستوراتی است که توسط جنگو آماده شده و با اجرای آن، بدنه اصلی پروژه ساخته می‌شود. این بدنه، شامل تعدادی پوشه و فایل است که ما بعداً از آن ها استفاده خواهیم کرد. + +نام برخی از این فایل‌ها و پوشه‌ها برای جنگو بسیار مهم است. شما نباید نام فایل‌‌هایی که الان می‌خواهیم بسازیم را تغییر دهید. همچنین تغییر پوشه‌های آنها هم ایده خوبی نیست. جنگو باید در یک ساختار مشخص مورد استفاده قرار گیرد تا بتواند موارد مهم را پیدا کند. + +> به یاد داشته باشید که همه دستورات را در محیط مجازی (virtualenv) اجرا کنید. اگر پیشوند `(myvenv)` را در کنسول خط فرمان نمی‌بینید، باید محیط مجازی را فعال کنید. فعال کردن محیط مجازی را در قسمت **کارکردن با محیط مجازی** از بخش **نصب جنگو** توضیح داده‌ایم. در ویندوز با تایپ `myvenv\Scripts\activate` و در لینوکس یا مک با نوشتن `source myvenv/bin/activate` می‌توانید محیط مجازی را فعال کنید. + + + +در کنسول لینوکس یا مک باید دستورات زیر را اجرا کنید. **فراموش نکنید که `علامت نقطه` را در آخر عبارت بگذارید!** + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> علامت `.` مهم است برای اینکه به سیستم می‌گوید که جنگو را در همین پوشه جاری نصب کند (علامت `.` به پوشه ای که در حال حاضر در آن هستیم اشاره میکند). +> +> **نکته** وقتی دستور بالا را می‌نویسید به یاد داشته باشید که فقط بخشی را می‌نویسید که با `django-admin` شروع می‌شود. بخش `(myvenv) ~/djangogirls$` نشان می‌دهد که شما باید دستورات ورودی را در مقابل آن بنویسید. + + + + + +در ویندوز باید دستور زیر را اجرا کنید. **(فراموش نکنید که `علامت نقطه` را در انتها بگذارید)**: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> علامت `.` مهم است برای اینکه به سیستم می‌گوید که جنگو را در همین پوشه جاری نصب کند (علامت `.` به پوشه ای که در حال حاضر در آن هستیم اشاره میکند). +> +> **نکته** وقتی دستور بالا را می‌نویسید به یاد داشته باشید که فقط بخشی را می‌نویسید که با `django-admin.exe` شروع می‌شود. بخش `(myvenv) C:\Users\Name\djangogirls>` نشان می‌دهد که شما باید دستورات ورودی را در مقابل آن بنویسید. + + + +`django-admin.py` دستوری است که پوشه‌ها و فایل‌ها را برای شما می‌سازد. الان باید ساختار پوشه‌ها و فایل‌های شما شبیه به این باشد: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **نکته**: در ساختار پوشه‌ها، شما پوشه `venv` را هم که قبلاً ساخته ایم خواهید دید. + +`manage.py` دستوری است که به مدیریت سایت کمک می‌کند. به کمک این دستور (و برخی چیزهای دیگر) و بدون نصب نرم افزارهای دیگر می‌توانیم یک وب سرور بر روی کامپیوتر خود راه اندازی کنیم. + +فایل `settings.py` حاوی تنظیمات وبسایت شما است. + +یادتان می‌آید در مورد حامل نامه و این موضوع که: کجا را باید نگاه کند تا بتواند نامه را به مقصد برساند‌، صحبت کردیم؟ فایل `urls.py` شامل الگوهایی است که توسط `urlresolver` استفاده می‌شوند. + +اجازه بدهید الان از سایر فایل‌ها چشم‌پوشی کنیم چون آن‌ها را تغییر نخواهیم داد. تنها چیزی که باید مواظب آن باشید این است که آن‌ها را اشتباهی پاک نکنید! + +## تغییر تنظیمات + +می‌خواهیم کمی تغییرات در فایل `mysite/settings.py` ایجاد کنیم. این فایل را در ویرایشگر کد، که پیش از این نصب کرده اید باز کنید. + +**نکته**: به یاد داشته باشید که فایل `settings.py`، یک فایل معمولی مانند بقیه فایل‌ها است. شما می‌توانید این فایل را به کمک ویرایشگر کد با استفاده از منو "file -> open"، باز کنید. از این طریق یک پنجره معمولی باز می‌شود که می‌توانید به کمک آن فایل `settings.py` را پیدا کنید و آن را انتخاب کنید. به جای این کار، می‌توانید در بین پوشه‌ها، پوشه djangogirls را پیدا کنید بر روی آن راست کلیک کنید. سپس نام ویرایشگر کد خود را از لیست به نمایش درآمده انتخاب کنید. انتخاب ویرایشگر مهم است چرا که ممکن است نرم افزارهای دیگر هم فایل را باز کنند ولی اجازه ویرایش کردن به شما ندهند. + +خیلی خوب خواهد بود که زمان درست را در وبسایت خود داشته باشیم. به [لیست منطقه های زمانی ویکیپدیا](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) بروید و محدوده زمانی مناسب را برای خود انتخاب کنید (TZ) (مثلاً `Asia/Tehran`). + +در فایل `settings.py` خطی را که حاوی `TIME_ZONE` است پیدا کنید و آن را اصلاح کنید تا منطقه زمانی شما را نشان دهد. مثلاً: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Asia/Tehran' +``` + +یک شناسه زبان شامل دو بخش است یکی زبان، مثلاً `en` برای انگلیسی و `fa` برای فارسی، و دیگری کد کشور، مثلاً `de` برای آلمان و `ir` برای ایران. اگر انگلیسی زبان اصلی شما نیست می‌توانید این شناسه را تغییر دهید تا پیغام‌های جنگو به زبان خودتان برای شما نمایش داده شود. بنابراین شما ترجمه دکمه "Cancel" را به زبانی که در اینجا معرفی کرده اید خواهید دید. [جنگو به زبان‌های زیادی ترجمه شده و قابل استفاده است](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +اگر زبان دیگری را می‌خواهید شناسه زبان را در خط زیر تغییر دهید: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +علاوه بر این نیاز داریم تا آدرس فایل‌های ثابت یا ایستا را نیز اضافه کنیم. (بعداً به طور کامل در این دوره آموزشی به فایل‌های ثابت و CSS خواهیم پرداخت.) به *انتهای* فایل بروید و دقیقاً زیر ورودی `STATIC_URL`، یک خط جدید با عنوان `STATIC_ROOT` اضافه کنید: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +وقتی در این فایل `DEBUG` برابر با `True`باشد و `ALLOWED_HOSTS` خالی باشد، مقادیر هاست `['localhost', '127.0.0.1', '[::1]']` خواهد بود. این هاست در هنگام انتشار وبسایت روی اینترنت، با هاست PythonAnywhere هماهنگ نخواهد بود پس تنظیمات را به این شکل تغییر می‌دهیم: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **نکته**: اگر از کروم بوک استفاده می‌کنید، این خط را هم به انتهای فایل settings.py اضافه کنید: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> اگر از cloud9 استفاده می‌کنید `.amazonaws.com` را به `ALLOWED_HOSTS` اضافه کنید +> +> اگر شما پروژه خود را بر روی `Glitch.com` میزبانی می‌کنید، اجازه دهید که از کلید مخفی جنگو یا Djanog secret key پروژه شما که باید محرمانه بماند محافظت کنیم (در غیر اینصورت هر کس که پروژه شما را بررسی کند آن را خواهد دید): +> +> - در ابتدا، یک کلید مخفی شانسی می‌سازیم. ترمینال Glitch را دوباره باز کنید و دستورات زیر را تایپ کنید: +> +> {% filename %}خط فرمان{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> این کار باعث خواهد شد که یک رشته اتفاقی از کاراکترها و حروف ساخته شود، چیزی که به عنوان یک کلید مخفی برای پروژه جنگو شما کاملاً مناسب است. ما این کلید را در فایل `.env` در Glitch اضافه می‌کنیم، این فایل درصورتی توسط Glitch به ما نشان داده می‌شود که ما صاحب پروژه باشیم. +> +> - فایلی به نام `.env` در پوشه اصلی پروژه بسازید و کدهای زیر را در آن قرار دهید: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - سپس فایل settings پروژه جنگو را با تغییرات زیر به روز رسانی کنید تا کلید مخفی به آن اضافه شود: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - کمی پایین‌تر در همان فایل، نام وبسایت جدید Glitch شما را اضافه می‌کنیم: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> مقدار `PROJECT_DOMAIN` به صورت اتوماتیک توسط Glitch ایجاد می‌شود. این مقدار وابسته به نام پروژه شماست. + +## راه اندازی یک پایگاه داده + +تعداد بسیار زیادی پایگاه داده وجود دارد که می‌تواند داده های وبسایت شما را ذخیره کند. ما از پایگاه داده پیشفرض `sqlite3` استفاده می‌کنیم. + +این پایگاه داده از قبل در این بخش از فایل `mysite/settings.py` تعریف شده است: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +برای ساختن یک پایگاه داده برای وبسایتمان، دستور زیر را در کنسول خط فرمان اجرا می‌کنیم: `python manage.py migrate` (هنگام اجرای این دستور باید در پوشه `djangogirls` باشیم جایی که فایل `manage.py` قرار دارد). اگر همه چیز خوب پیش برود باید چیزی شبیه به این را ببینیم: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +تمام شد! وقت آن است که وب سرور را اجرا کنیم و ببینیم آیا وبسایت ما کار می‌کند! + +## فعال کردن وب سرور + +شما باید در پوشه‌ای باشید که فایل `manage.py` در آن قرار دارد. (در پوشه `djangogirls`). در کنسول خط فرمان، وب سرور را به کمک این دستور فعال می‌کنیم `python manage.py runserver`: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +اگر در Chromebook کار می‌کنید از این دستور استفاده کنید: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +یا اگر از Glitch استفاده می‌کنید به کمک دستور زیر: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +اگر در ویندوز کار می‌کنید و با خطای `UnicodeDecodeError` مواجه شدید، از دستور زیر استفاده کنید: + +{% filename %}خط فرمان{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +حالا زمان آن است که چک کنید وبسایت کار می‌کند یا نه. مرورگر خود را باز کنید (فایرفاکس، کروم، سافاری، اینترنت اکسپلورر یا هر چیز دیگر) و آدرس زیر را وارد کنید: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +اگر از Chromebook و Cloud9 استفاده می‌کنید، در پنجره pop-up که در گوشه ی بالا، سمت راست پنجره ی خط فرمان، که در حال اجرای وب سرور است، باز شده است، بر روی آدرس URL ظاهر شده کلیک کنید. این آدرس چیزی شبیه به این است: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +یا در Glitch: + + https://name-of-your-glitch-project.glitch.me + + +تبریک! شما اولین وبسایت خود را ساخته اید و با یک وب سرور آن را فعال کرده اید! فوق العاده نیست؟ + +![Install worked!](images/install_worked.png) + +توجه داشته باشید که یک کنسول خط فرمان در هر لحظه فقط یک کار را می‌تواند انجام دهد و کنسول خط فرمان که شما قبل‌تر باز کرده‌اید در حال اجرای وب سرور است. تا زمانی که وب سرور در حال اجراست و منتظر است تا درخواستی به آن برسد می‌توان چیزی تایپ کرد ولی هیچ دستور جدیدی را نمی‌توان اجرا کرد. + +> نحوه عملکرد وب سرور را در بخش **اینترنت چگونه کار می‌کند** دوره کرده ایم. + +برای اینکه در زمان فعال بودن وب سرور، دستورات بیشتری را در کنسول خط فرمان تایپ کنید باید یک کنسول جدید باز کنید و محیط مجازی خود را فعال کنید. برای آنکه روش باز کردن یک کنسول جدید را مرور کنید می‌توانید به بخش [آشنایی با خط فرمان](../intro_to_command_line/README.md) نگاهی بیندازید. برای قطع فعالیت وب سرور، به همان کنسولی بروید که وب سرور در آن فعال است و کلید CTRL و C را با هم بزنید (در ویندوز ممکن است لازم باشد کلید CTRL را با کلید Break بزنید). + +برای قدم بعدی آماده هستید؟ حالا وقت آن است که کمی محتوا بسازیم! \ No newline at end of file diff --git a/fa-IR/django_templates/README.md b/fa-IR/django_templates/README.md new file mode 100644 index 00000000000..06eefa0c9d7 --- /dev/null +++ b/fa-IR/django_templates/README.md @@ -0,0 +1,108 @@ +# templates در جنگو + +وقت آن است که داده‌ها را در وبسایت نمایش دهیم. جنگو چندین **template tag** مفید در اختیار ما قرار می‌دهد. + +## template tag چیست؟ + +میدانیم که در کدهای HTML نمی‌توانیم از کد های پایتون استفاده کنیم،به این دلیل که مرورگر نمی‌تواند کد پایتون را درک کند. مرورگرها فقط HTML را می‌فهمند. همینطور می‌دانیم که HTML ایستا است، در حالی که پایتون بسیار پویاتر است. + +** template tags در جنگو ** ما را قادر می‌سازد تا اشیا پایتونی را به HTML انتقال دهیم، بنابراین شما می‌توانید با سرعت بیشتری وبسایت‌های پویا توسعه دهید. چه خوب! + +## نمایش دادن قالب لیست پست‌های وبلاگ + +در بخش قبلی، ما لیستی از پست‌ها را در قالب متغیر `posts` به template دادیم. حالا آن را به وسیله HTML نمایش می‌دهیم. + +برای چاپ یک متغیر در template های جنگو، نام متغیر را درون دو جفت آکولاد قرار می دهیم. مانند کد زیر: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +این مورد را در قالب `blog/templates/blog/post_list.html` امتحان کنید. آن را در ویرایشگر کد باز کنید، و هر چیزی از دومین `
` تا سومین `
` را با `{{ posts }}` جایگزین کنید. فایل را ذخیره کنید، و صفحه را برای دیدن نتیجه refresh کنید: + +![تصویر 13.1](images/step1.png) + +همینطوری که مشاهده می‌کنید، تمام چیزی که به دست آورده‌ایم این است: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +این به معنای آن است که جنگو این متغیر را به عنوان لیستی از اشیا در نظر می‌گیرد. آیا از بخش **معرفی پایتون** بخاطر دارید که چگونه می‌توانیم لیست‌ها را نمایش دهیم؟ بله، با حلقه for ! در یک template جنگو شما این کار را به صورت زیر انجام خواهید داد: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +این کار را در template خود امتحان کنید. + +![تصویر 13.2](images/step2.png) + +کار میکند! اما ما میخواهیم تا پست ها مانند پست های ایستایی که پیش از این در بخش **معرفی HTML** ساختیم، نمایش داده شود. میتوانید HTML و template tag را با هم استفاده کنید. قسمت `body` به صورت زیر خواهد بود: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %} هر چیزی که بین `{% for %}` و `{% endfor %}` قرار می‌دهید، برای هر شی در لیست تکرار می‌شود. صفحه خود را refresh کنید: {% endraw %} + +![تصویر 13.3](images/step3.png) + +آیا توجه کردید که این بار از نشانه گذاری متفاوتی استفاده کردیم؟ (`{{ post.title }}` یا `{{ post.text }}`)؟ ما در حال دسترسی به داده‌های موجود در هر فیلد تعریف شده در مدل `Post` هستیم. همچنین، `|linebreaksbr` متن پست‌ها را از فیلتری رد می‌کند که line-break ها را به پاراگراف تبدیل می‌کند. + +## یک مورد دیگر + +خوب است اگر بدانیم وب سایت شما روی اینترنت عمومی نیز به درستی کار می‌کند یا نه، درست است؟ بیایید تا دوباره انتشار آن را روی PythonAnywhere امتحان کنیم. خلاصه‌ای از مراحل در زیر آورده شده‌ است… + +* ابتدا کد خود را روی گیتهاب push کنید + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* سپس دوباره به [PythonAnywhere](https://www.pythonanywhere.com/consoles/) وارد شوید و به **Bash console** خود بروید ( یا یک کنسول خط فرمان جدید باز کنید)، و دستورات زیر را اجرا کنید: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(به خاطر داشته باشید `` را با زیردامنه PythonAnywhere خود جایگزین کنید، بدون علامت های <>) + +* سرانجام، به برگه ["Web" page](https://www.pythonanywhere.com/web_app_setup/) بروید و **Reload** را انتخاب کنید. (برای رسیدن به سایر صفحات در PythonAnywhere از دکمه منو در سمت بالا و راست صفحه استفاده کنید.) به روز رسانی شما باید در آدرس https://subdomain.pythonanywhere.com موجود باشد در مرورگر خود آن را امتحان کنید! اگر پست‌های وبلاگی شما در PythonAnywhere با پست‌های شما در سرور فعال روی کامپیوترتان یکی نیست، نگران نباشید همه چیز مرتب است. پایگاه داده موجود روی کامپیوتر شما و PythonAnywhere، برخلاف سایر فایل‌های شما، با یکدیگر یکسان سازی نمی‌شوند و یکی نیستند. + +تبریک! حالا سعی کنید که یک پست جدید از طریق پنل مدیریت جنگو (به یاد دارید که published_date را اضافه کردیم) اضافه کنید مطمئن شوید که در بخش مدیریت جنگو در وبسایت PythonAnywhere باشید، https://subdomain.pythonanywhere.com/admin. سپس صفحه خود را دوباره بارگزاری کنید و ببینید آیا پست جدید به آن اضافه شده است. + +جذاب نیست؟ به شما افتخار می‌کنیم! کمی از کامپیوتر خود دور شوید، لازم است کمی استراحت کنید. :) + +![تصویر 13.4](images/donut.png) \ No newline at end of file diff --git a/fa-IR/django_urls/README.md b/fa-IR/django_urls/README.md new file mode 100644 index 00000000000..164462a0938 --- /dev/null +++ b/fa-IR/django_urls/README.md @@ -0,0 +1,103 @@ +# URL ها در جنگو + +ما در آستانه ساخت اولین صفحه وب هستیم: یک صفحه برای وبلاگ شما! ولی قبل از آن بیایید کمی در مورد آدرس دهی در جنگو یادبگیریم. + +## URL چیست؟ + +یک URL یک آدرس اینترنتی است. شما هربار که وبسایتی را بازدید می‌کنید می‌توانید آدرس آن را ببینید، این آدرس، در address bar یا پنجره آدرس مرورگر دیده می‌شود. (بله! `127.0.0.1:8000` یک آدرس (URL) است! و `https://djangogirls.org` هم یک آدرس (URL) است.) + +![URL](images/url.png) + +هر صفحه‌ای در اینترنت آدرس خود را لازم دارد. به این روش برنامه ما متوجه می‌شود که چه چیزی را باید به کاربری که یک آدرس را باز می‌کند نشان بدهد. در جنگو ما از چیزی به نام `URLconf` استفاده می‌کنیم (URL configuration). URLconf مجموعه‌ای از الگوها است که جنگو به کمک آن می‌تواند متوجه شود که آدرس درخواست شده باید به کدام ویو، ارجاع داده شود. + +## آدرس ها در جنگو چطور کار می‌کنند؟ + +حالا فایل `mysite/urls.py` را در ویرایشگر کد خود باز کنید و ببینید چگونه است: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +همانطور که می‌بینید، اینجا جنگو چیزهایی برای ما گذاشته است. + +به خطوط بین نقل قول سه تایی (`'''` یا `"""`) docstrings یا توضیحات سند گفته می‌شود. شما می‌توانید این توضیحات را در بالای فایل، کلاس یا تابع بنویسید و عملکرد آن را شرح دهید. این خطوط توسط پایتون اجرا نمی‌شوند. + +همچنین، آدرس بخش مدیریت که در بخش قبل دیده اید، اینجا وجود دارد: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +معنی این خط این است که هر آدرسی که با `admin/` شروع شود، جنگو *view* مربوط به آن را پیدا خواهد کرد. در این مورد خاص، ما تعداد زیادی آدرس را اضافه کرده‌ایم که همه آن‌ها در این فایل نیامده‌اند - این شکل از خلاصه کردن آدرس‌ها خوانایی وتمیزی کدها را افزایش می‌دهد. + +## اولین آدرس جنگویی شما! + +زمان آن است که اولین آدرس خود را بسازید! ما می‌خواهیم که 'http://127.0.0.1:8000/' صفحه اصلی وبلاگ ما باشد که در آن لیستی از پست‌ها نمایش داده شود. + +همچنین می‌خواهیم که فایل `mysite/urls.py` را تمیز نگه داریم، در نتیجه آدرس‌ها را از اپلیکیشن `blog` ، در فایل اصلی آدرس‌ها `mysite/urls.py` فراخوانی می‌کنیم. + +به پیش برویم و خطی را اضافه کنیم که `blog.urls` را بارگذاری می‌کند. همچنین لازم است که خط `from django.urls…` را عوض کنید چرا که ما اینجا از تابع `include` استفاده می‌کنیم، بنابراین لازم است که شما دستور import را به این خط اضافه کنید. + +فایل `mysite/urls.py` شما باید چیزی شبیه به این شده باشد: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +حالا جنگو هر درخواستی که به آدرس 'http://127.0.0.1:8000/' ارسال شود را به `blog.urls` ارسال می‌کند و دستورالعمل‌های بعدی را در آنجا جستجو می‌کند. + +## blog.urls + +در پوشه `blog` یک فایل خالی به نام `urls.py` بسازید و آن را در ویرایشگر کد باز کنید. بسیار خوب! این دو خط را به آن اضافه کنید: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +در اینجا ما تابع جنگویی `path` و تمام `view` ها از اپلیکیشن `blog` را بارگذاری کرده‌ایم (هرچند که هنوز هیچ view نداریم ولی تا چند دقیقه دیگر سراغ آن خواهیم رفت!) + +بعد از این می‌توانیم اولین الگو آدرس را اضافه کنیم: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +همانطور که می‌بینید ما یک `view` به نام `post_list` را به آدرس پایه وبلاگ نسبت داده‌ایم. این الگوی URL، شامل یک رشته خالی از کاراکتر است و سیستم بررسی آدرس جنگو نام دامنه را (مثلاً http://127.0.0.1:8000/) که پیشوندی برای همه آدرس‌ها است، در نظر نمی‌گیرد. این الگو به جنگو می‌گوید که اگر کسی آدرس 'http://127.0.0.1:8000/' را وارد کرد باید به `views.post_list` بروی. + +قسمت آخر، `name='post_list'`، نام آدرس است که برای تعیین هویت یک view استفاده می‌شود. این نام می‌تواند کاملاً شبیه نام view باشد یا نام کاملاً متفاوتی داشته باشد. ما بعداً از آدرس‌های نامگذاری شده در پروژه استفاده خواهیم کرد بنابراین مهم است که برای هر آدرسی نام، تعریف شود. علاوه بر این تلاش خواهیم کرد که نام آدرس‌ها، منحصر به فرد و برای به خاطر سپردن، ساده باشد. + +اگر الان تلاش کنید تا به آدرس http://127.0.0.1:8000/ بروید احتمالاً با پیغام خطای موجود نبودن صفحه مواجه خواهید شد. این پیغام به خاطر این است که سرور (یادتان هست که تایپ می‌کردیم `runserver`؟) فعال نیست. به کنسول سرور نگاه کنید تا ببینید دلیل آن چیست. + +![خطا](images/error1.png) + +کنسول سرور یک پیعام خطا نشان می‌دهد ولی نگران نباشید، ابزار سودمندی است: این پیغام خطا می‌گوید که **no attribute 'post_list'**. این نام همان *view* است که جنگو تلاش می‌کند آن را پیدا و اجرا کند، اما ما هنوز آن را نساخته‌ایم. در این مرحله `/admin/` شما هم کار نمی‌کند. نگران نباشید، سراغ آن هم خواهیم رفت. اگر پیغام خطای دیگری دریافت کردید یک بار وب سرور را قطع و مجدداً فعال کنید. برای این کار، در پنجره کنسولی که وب سرور در آن در حال اجرا است، با زدن کلیدهای Ctrl+C (کلید Control و کلید C با هم)، وب سرور را متوقف کنید. در ویندوز ممکن است لازم باشد کلیدهای Ctrl+Break را بزنید. سپس لازم است که وب سرور را مجدداً با دستور `python manage.py runserver` راه اندازی کنید. + +> اگر می‌خواهید بیشتر در مورد URLconfs جنگو بدانید، به مستندات رسمی آن نگاهی بیندازید: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/fa-IR/django_views/README.md b/fa-IR/django_views/README.md new file mode 100644 index 00000000000..7a51ba2acf9 --- /dev/null +++ b/fa-IR/django_views/README.md @@ -0,0 +1,44 @@ +# ساخت view در جنگو! + +وقتشه که از شر باگی که تو فصل قبلی ایجاد کردیم راحت بشیم :) + +یک *view* یا نما بخشی از برنامه است که "منطق" برنامه در آن قرار می‌گیرد. این مولفه اطلاعات مورد نیاز را از `model` هایی که قبلا ایجاد کرده‌اید می گیرد و به `template` ارسال می‌کند. ما در بخش بعد یک قالب یا template خواهیم ساخت. View ها صرفاً توابع پایتونی هستند که کمی پیچیده‌تر از توابعی هستند که در بخش **آشنایی با پایتون** نوشتیم. + +ویوها در فایل `views.py` قرار دارند. ما *ویوهای* مورد نظرمان را در فایل `blog/views.py` اضافه خواهیم کرد. + +## blog/views.py + +خب، بیایید این فایل را در ویرایشگر کد باز کنیم و ببینیم چه چیزی در آن هست: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +هنوز چیز زیادی در آن نیست. + +به یاد داشته باشید که خط هایی که با `#` شروع می‌شوند کامنت یا توضیحات هستند - به این معنی که این خط ها توسط پایتون اجرا نمی‌شوند. + +حالا بیایید همانند توصیه‌ای که در خود فایل شده است یک *view* بسازیم. این ویو بسیار خلاصه را زیر کامنت موجود در فایل اضافه کنید: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +همانطور که می‌بینید ما یک تابع ساختیم ( دستور `def` تابع `post_list` را که یک آرگومان به نام `request` می‌گیرد صدا می‌زند و در نهایت به کمک یک تابع دیگر به نام `render` قالب `blog/post_list.html` را باز می‌گرداند (`return`)). + +فایل را ذخیره کنید و در مرورگر خود آدرس http://127.0.0.1:8000/ را بزنید و ببینید چه چیزی دیده می‌شود. + +باز هم خطا! ببینید چه اتفاقی افتاده است: + +![خطا](images/error.png) + +حداقل می‌توان دید که سرور در حال کار است اما هنوز، همه چیز کامل نیست، درست است؟ نگران نباشید این فقط یک صفحه خطاست، لازم نیست بترسید! دقیقاً شبیه خطاهای موجود در کنسول، این خطاها هم کاملاً مفید هستند. شما می‌توانید ببینید که با خطای *TemplateDoesNotExist* یعنی قالب وجود ندارد، مواجه شده اید. خب بگذارید این خطا را درست کنیم و در بخش بعد یک قالب یا template بسازیم! + +> با خواندن مستندات رسمی جنگو اطلاعات بیشتری در مورد ویوها یاد خواهید گرفت: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/fa-IR/dynamic_data_in_templates/README.md b/fa-IR/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..32450f053a8 --- /dev/null +++ b/fa-IR/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# داده‌های پویا در template ها + +ما قطعات مختلفی داریم: مدل `Post` که در فایل `models.py` تعریف شده است، `post_list` که در فایل `views.py` تعریف شده و یک template که ساخته‌ایم. ولی واقعاً چطور پست‌های وبلاگمان را در قالب HTML نشان می‌دهیم؟ چون این کاری است که می‌خواهیم انجام دهیم؛ گرفتن محتوا (مدل‌هایی که در پایگاه داده ذخیره شده اند) و نشان دادن آن در قالب مورد نظر خودمان، درست است؟ + +این دقیقاً همان چیزی است که *view*ها برای آن طراحی شده اند: وصل کردن مدل ها و قالب‌ها. در *ویو* `post_list` ما نیاز داریم که مدل مورد نظر را بگیریم و آن را به تمپلیت مناسب آن ارجاع دهیم. ما در *ویو* تصمیم می‌گیریم که چه چیزی (model) در تمپلیت نشان داده شود. + +بسیار خوب، چطور به این هدف برسیم؟ + +لازم است که فایل`blog/views.py` را در ویرایشگر کد باز کنیم. تا اینجا *ویو* `post_list` شبیه به این است: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +به یاد دارید که در مورد اضافه کردن کدهای نوشته شده در فایل‌های مختلف صحبت کردیم؟ حالا وقت آن است که مدلی را که در فایل `models.py` نوشتیم به این فایل اضافه کنیم. ما خط `from .models import Post` را به این صورت اضافه می‌کنیم: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +نقطه قبل از `models` به معنی *پوشه جاری* یا *اپلیکیشن جاری* است. هر دو فایل `views.py` و `models.py` در یک پوشه قرار دارند. پس به این معنی است که ما می‌توانیم از `.` به همراه نام فایل (بدون پسوند `.py`) استفاده کنیم. سپس نام مدل را فراخوانی می‌کنیم (`Post`). + +قدم بعدی چیست؟ برای اینکه پست‌های وبلاگی واقعی که قبلاً ساخته ایم را فراخوانی کنیم به چیزی نیاز داریم که به آن `کوئری ست` یا `QuerySet` می‌گوییم. + +## QuerySet + +شما باید با نحوه کار کوئری ست‌ها آشنا باشید. ما در [بخش ORM جنگو](../django_orm/README.md) در مورد آن‌ها صحبت کرده ایم. + +حالا ما پست‌هایی را می‌خواهیم که بر اساس `تاریخ انتشار` یا published_date، مرتب شده اند، درست است؟ این کار را هم در بخش کوئری ست انجام داده ایم! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +حالا فایل `blog/views.py` را در ویرایشگر کد باز کنید و این تکه کد را به تابع `def post_list(request)` اضافه کنید. فراموش نکنید که خط `from django.utils import timezone` را هم به بالای فایل اضافه کنید: + +{% filename %}blog/views.py{% endfilename %} + +```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 در لیست ارسال های بلاگ، دو کار باقی مانده است که باید انجام شود: + +1. فرستادن کوئری ست `posts` به تمپلیت با تغییر تابع `render`. الان این کار را انجام می‌دهیم. +2. اصلاح تمپلیت برای نمایش دادن کوئری ست `posts`. این کار را در بخش‌های بعد انجام خواهیم داد. + +توجه داشته باشید که ما یک *متغیر* برای کوئری ست مان درست کردیم: `posts`. آن را به عنوان نام کوئری ست در نظر بگیرید. از این به بعد ما به کمک همین نام به این کوئری ست مراجعه می‌کنیم. + +در تابع `render` ما یک پارامتر `request` داریم (درخواستی است که کاربر از طریق اینترنت برای ما ارسال کرده است) و یک پارامتر دیگر که نام فایل template است (`'blog/post_list.html'`). آخرین پارامتر ما، `{}`، محلی است که می‌توانیم چیزهایی را برای استفاده در template در آن قرار دهیم. باید برای این چیزها اسم تعریف کنیم (مثلاً همین متغیر `'posts'`). :) باید به این صورت برای فایل تمپلیت ارسال شوند: `{'posts': posts}`. توجه کنید که بخش سمت چپ علامت `:` از نوع رشته یا string است و لازم است که با علامت نقل قول `''` محصور شود. + +در نتیجه فایل `blog/views.py` ما شبیه به این خواهد شد: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +همین! وقت آن است که به فایل template برگردیم و این کوئری ست را نمایش دهیم! + +دوست دارید در مورد کوئری ست‌ها بیشتر بدانید؟ به اینجا نگاهی بیندازید: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/fa-IR/extend_your_application/README.md b/fa-IR/extend_your_application/README.md new file mode 100644 index 00000000000..eb64c918205 --- /dev/null +++ b/fa-IR/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# برنامه خود را توسعه دهید + +ما تقریباً تمام مراحل مختلف ضروری برای ساختن وبسایتمان را کامل کرده‌ایم: می‌دانیم که چطور مدل، URL، ویو و تمپلیت بنویسیم. علاوه بر این می‌دانیم که چطور وبسایتمان را زیباتر کنیم. + +زمان تمرین است! + +اولین چیزی که در وبلاگمان لازم داریم صفحه‌ای است که یک پست را نشان دهد، درست است؟ + +ما یک مدل `Post` داریم پس لازم نیست چیزی به فایل `models.py` اضافه کنیم. + +## ساختن لینک به جزییات پست در تمپلیت + +ما با اضافه کردن یک لینک به فایل `blog/templates/blog/post_list.html` آغاز می‌کنیم. این فایل را در ویرایشگر کد باز کنید و تا اینجا باید شبیه به این باشد: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %} ما می‌خواهیم در لیست پست ها، یک لینک از عنوان پست وبلاگی به جزییات پست داشته باشیم. عبارت `

{{ post.title }}

` را تغییر دهید تا به صفحه جزییات پست لینک شود: {% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %} زمان آن است که عبارت رازآلود `{% url 'post_detail' pk=post.pk %}` را توضیح دهیم. همانطور که ممکن است حدس زده باشید این علامت `{% %}` به معنی آن است که ما از سیستم template tag جنگو استفاده می‌کنیم. این بار ما از یک tag استفاده خواهیم کرد که برایمان یک URL بسازد!{% endraw %} + +بخش `post_detail` به معنی آن است که جنگو انتظار دارد یک آدرس به نام post_detail، در فایل `blog/urls.py` وجود داشته باشد + +حالا معنی `pk=post.pk` چیست؟ `pk` مخفف primary key (کلید اصلی) است که یک نام منحصر به فرد برای هر ردیف از داده‌ها در پایگاه داده می‌باشد. هر مدل جنگو یک فیلد به عنوان کلید اصلی دارد، و سوای اینکه چه نام دیگری داشته باشد، همواره به عنوان pk قابل ارجاع است. چون ما در مدل `Post` کلید اصلی نساخته بودیم، جنگو یکی برای ما ساخته است (به طور پیشفرض فیلدی که نام آن "id" است، عددی را در خود ذخیره می‌کند که با هر دیتای جدید یکی به آن اضافه می‌شود مثلاً 1، 2، 3 ) و برای هر پست جدید در وبلاگ یکی به آن اضافه می‌کند. ما با نوشتن `post.pk` به کلید اصلی دسترسی پیدا می‌کنیم، همانطور که به فیلدهای دیگر (مانند `title` و `author`) در آبژکت `Post`، دسترسی داشته‌ایم. + +حالا وقتی به آدرس http://127.0.0.1:8000/ می‌رویم با خظا مواجه می‌شویم (همانطور که انتظار داشتیم، چرا که ما هنوز برای `post_detail` ، یک آدرس یا یک *view* نساخته ایم). چیزی شبیه به این: + +![خطا NoReverseMatch](images/no_reverse_match2.png) + +## ساختن آدرس برای جزییات یک پست وبلاگ + +بیایید یک URL برای *ویو* `post_detail` در فایل `urls.py` بسازیم! + +ما می‌خواهیم جزییات اولین پست ما در این **URL** دیده شود: http://127.0.0.1:8000/post/1/ + +بیایید یک آدرس در فایل `blog/urls.py` بسازیم تا جنگو را به *view* با نام `post_detail` هدایت کند که جزییات کامل یک پست وبلاگ را نشان می‌دهد. فایل `blog/urls.py`را در ویرایشگر کد باز کنید و خط `path('post//', views.post_detail, name='post_detail'),` را اضافه کنید، چیزی شبیه به این می‌شود: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +بخش `post//` یک الگوی URL را معرفی می‌کند که برای شما توضیح خواهیم داد: + +- `post/` نشان می‌دهد که آدرس باید با کلمه **post** شروع شده باشد و در ادامه آن یک **/** وجود داشته باشد. تا اینجا همه چیز خوب است. +- `` این بخش ممکن است کمی گیج کننده باشد، این عبارت به این معنی است که جنگو انتظار دارد که یک عدد صحیح دریافت کند و مقدار آن را به یک متغیر به نام `pk` نسبت خواهد داد. +- `/` - درنهایت ما به یک **/** در انتهای آدرس نیاز داریم. + +یعنی اگر شما آدرس `http://127.0.0.1:8000/post/5/` را در مرورگر خود وارد کنید جنگو متوجه خواهد شد که شما به دنبال یک *view* به نام `post_detail` هستید و مقدار متغیر `pk` را برابر `5` قرار می‌دهد و این اطلاعات را به *view* مورد نظر ارسال می‌کند. + +بسیار عالی، ما یک الگوی آدرس جدید به فایل `blog/urls.py` اضافه کردیم! حالا صفحه http://127.0.0.1:8000/ را دوباره بارگزاری کنید، بووم! سرور دوباره متوقف شده است. به کنسول نگاهی بیندازید، یک پیغام خطای دیگر دیده می‌شود! + +![AttributeError](images/attribute_error2.png) + +یادتان هست که مرحله بعدی چیست؟ اضافه کردن ویو! + +## اضافه کردن ویو جزییات یک پست + +این بار *view* ما یک پارامتر اضافه دریافت کرده است، `pk`. *ویو* ما باید بتواند آن را دریافت کند، درست است؟ پس ما تابع خودمان را به این صورت تعریف می‌کنیم `def post_detail(request, pk):`. باید توجه داشته باشید که این پارامتر باید دقیقاً همان نامی را داشته باشد که ما در `urls` تعریف کرده‌ایم (`pk`). همچنین توجه کنید که حذف این متغیر، غلط است و باعث ایجاد خطا خواهد شد. + +حالا ما می‌خواهیم فقط و فقط یک پست وبلاگی را داشته باشیم. برای اینکار از کوئری ست به شکل زیر استفاده می‌کنیم: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +اما این کد یک مشکل دارد. اگر هیچ `Post` با `کلید اصلی` (`pk`) وجود نداشته باشد، یک خطای زشت دریافت خواهیم کرد! + +![خطا DoesNotExist](images/does_not_exist2.png) + +چنین چیزی را نمی‌خواهیم! اما خوشبختانه جنگو چیزی دارد که می‌تواند این مشکل را حل کند: `get_object_or_404`. در صورتی که هیچ `Post` با `pk` داده شده وجود نداشته باشد، یک صفحه خطای زیباتر یعنی صفحه `Page Not Found 404` را نشان خواهد داد. + +![صفحه پیدا نشد](images/404_2.png) + +خبر خوب اینکه شما می‌توانید صفحه `Page not found` اختصاصی برای خودتان را با سلیقه خودتان بسازید. اما این الان موضوع خیلی مهمی نیست بنابراین ما از آن رد خواهیم شد. + +وقت آن است که یک *ویو* به فایل `views.py` اضافه کنیم! + +در فایل `blog/urls.py` ما یک الگوی آدرس به نام `post_detail` ساختیم که به یک ویو با نام `views.post_detail` ارجاع داشت. این به این معنی است که جنگو انتظار دارد که یک تابع با نام `post_detail` در فایل `blog/views.py` وجود داشته باشد. + +زمان آن است که فایل `blog/views.py` را در ویرایشگر کد باز کنید و خطوط زیر را در ردیف `from` ها اضافه کنید: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +و در انتهای فایل، *ویو* خودمان را اضافه خواهیم کرد: + +{% filename %}blog/views.py{% endfilename %} + +```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](images/post_list2.png) + +کار می‌کند! ولی وقتی روی لینک مربوط به عنوان یک پست کلیک کنید چه اتفاقی می‌افتد؟ + +![خطا TemplateDoesNotExist](images/template_does_not_exist2.png) + +وای نه! یک خطای دیگر! اما حالا ما می‌دانیم که چطور با این خطا برخورد کنیم، درست است؟ ما باید یک تمپلیت اضافه کنیم! + +## ساختن یک تمپلیت برای جزییات پست وبلاگی + +در پوشه `blog/templates/blog` یک فایل به نام `post_detail.html` بسازید و آن را در ویرایشگر کد باز کنید. + +حالا کد زیر را تایپ کنید: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +یک بار دیگر ما فایل `base.html` را اضافه کرده‌ایم. ما می‌خواهیم در بلوک `content` ، جزییات یک پست منتشر شده (اگر چنین پستی وجود داشت) شامل عنوان و متن را نشان دهیم. اما باید در مورد چند موضوع مهم صحبت کنیم، خب؟ + +{% raw %}`{% if ... %} ... {% endif %}` یک تمپلیت تگ است که وقتی می‌خواهیم چیزی را چک کنیم از آن استفاده می‌کنیم. (عبارت `if ... else ...` را از بخش **آشنایی با پایتون** به یاد دارید؟) در این سناریو ما می‌خواهیم بررسی کنیم آیا بخش `published_date` مربوط به یک پست خالی نیست.{% endraw %} + +بسیار خوب، ما می‌توانیم صفحه وبلاگمان را دوباره بارگذاری کنیم و ببینیم آیا خطا `TemplateDoesNotExist` از بین رفته است یا نه. + +![صفحه جزییات پست](images/post_detail2.png) + +واو! بالاخره کار کرد! + +# زمان دیپلوی! + +خوب خواهد بود اگر ببینیم وبسایت شما هنوز روی PythonAnywhere کار میکند یا نه؟پس بیایید یک بار دیگر آن را منتشر کنیم. + +{% filename %}خط فرمان{% endfilename %} + + $ git status + $ git add . + $ 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](https://www.pythonanywhere.com/consoles/) تایپ کنید: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(یادتان باشد که `` را با زیر دامنه اصلی خود در PythonAnywhere عوض کنید البته بدون آکولادها.) + +## به روزرسانی فایل‌های ایستا در سرور + +سرورهایی مانند PythonAnywhere دوست دارند که با فایل‌های ایستا (مانند فایل‌های CSS) به گونه‌ای متفاوت از فایل‌های پایتون برخورد کنند، چرا که می‌توانند آن ها را بهینه کنند و سرعت لود شدن آن‌ها را افزایش دهند. در نتیجه هرگاه که ما تغییری در فایل‌های CSS می‌دهیم ، باید دستوری اضافه بر روی آن اجرا کنیم تا به سرور بگوییم که این فایل‌ها تغییر کرده اند. این دستور `collectstatic` نام دارد. + +ابتدا با فعال کردن محیط مجازی شروع کنیم اگر از قبل هنوز فعال نیست (PythonAnywhere از دستوری به نام `workon` برای این کار استفاده می‌کند این دستور دقیقاً شبیه `source myenv/bin/activate` است که شما بر روی کامپیوتر خودتان اجرا می‌کنید): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +دستور `manage.py collectstatic` تقریباً شبیه دستور `manage.py migrate` است. ما تغییراتی در کدها می‌دهیم و به جنگو می‌گوییم این تغییرات را *apply* (اعمال) کند، چه در فایل‌های ایستا در سرور باشد چه در پایگاه داده. + +به هرحال، الان ما آماده هستیم، به سراغ ["Web" page](https://www.pythonanywhere.com/web_app_setup/) بروید (از طریق دکمه menu در گوشه بالا و سمت راست کنسول) و دکمه **Reload** را بزنید و سپس به صفحه https://subdomain.pythonanywhere.com نگاه کنید تا نتیجه را ببینید. + +به نتیجه رسید! تبریک! :) \ No newline at end of file diff --git a/fa-IR/how_the_internet_works/README.md b/fa-IR/how_the_internet_works/README.md new file mode 100644 index 00000000000..92ce549d377 --- /dev/null +++ b/fa-IR/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# اینترنت چگونه کار می‌کند + +> برای خوانندگان در خانه: این فصل در ویدئو [نصب پایتون و کد ویرایشگر](https://www.youtube.com/watch?v=oM9yAA09wdc) توضیح داده شده است. +> +> این فصل "اینترنت چگونه کار می‌کند" از سخنرانی جسیکا مک کلر (http://web.mit.edu/jesstess/www/) الهام گرفته شده است. + +قطعاً شما هر روز از اینترنت استفاده می‌کنید. اما آیا می‌دانید در واقع وقتی شما آدرسی مثل https://djangogirls.org را در مرورگر خود تایپ می‌کنید، چه اتفاقی می‌افتد؟ + +اولین چیزی که باید بدانید این است که یک وب سایت از مجموعه‌ای از فایل‌ها تشکیل شده است که روی یک هارد دیسک ذخیره شده اند ـ دقیقاً مانند فیلم‌ها، آهنگ‌ها و تصاویر شما. با این وجود، وب سایت ها یک ویژگی منحصر به فرد دارند: کدهای کامپیوتری به نام HTML. + +اگر با برنامه نویسی آشنایی ندارید، ممکن است درک HTML در ابتدا سخت باشد، ولی مرورگر های شما (مثل گوگل کروم، سافاری، فایرفاکس و...) عاشق آن هستند. مرورگرها طراحی شده اند تا این کدها را درک کنند، دستورات آنها را دنبال کنند و فایل‌هایی را که وب سایت شما از آن تشکیل شده است، دقیقاً آنطور که می‌خواهید، نمایش دهند. + +مانند هر فایل دیگری، ما نیاز داریم تا فایل‌های HTML را نیز جایی بر روی هارد دیسک ذخیره کنیم. برای اینترنت، ما از کامپیوترهای مخصوص و قوی به نام *servers* استفاده می‌کنیم. این کامپیوترها صفحه نمایش، کیبورد یا موس ندارند برای آنکه وظیفه اصلی آن‌ها ذخیره اطلاعات و ارائه آن‌ها است. برای همین به آن‌ها *سرور* می‌گویند برای آنکه آن‌ها داده‌ها را *ارائه* می‌کنند (serve یعنی ارائه کردن). + +خب، ولی شما می‌خواهید بدانید که اینترنت چطور کار می‌کند، درست است؟ + +تصویری برای شما کشیده ایم! چیزی شبیه به این: + +![تصویر 1.1](images/internet_1.png) + +کمی به هم ریخته است، درست است؟ در واقع این شبکه‌ای از ماشین‌های به هم متصل شده است (همانطور که در بالا اشاره شد *سرورها* هستند). صدها و هزاران دستگاه! کیلومترها سیم و کابل دور دنیا! شما می‌توانید وبسایت نقشه کابل‌های زیردریایی (http://submarinecablemap.com) را ببینید تا با پیچیدگی شبکه آشنا شوید. این تصویری از این وبسایت است: + +![تصویر 1.2](images/internet_3.png) + +جذاب است، اینطور نیست؟ اما کشیدن یک سیم مستقیم بین هر دستگاه متصل شده به اینترنت با دیگر دستگاه‌ها ممکن نیست. بنابراین برای رسیدن به یک دستگاه (مثلاً دستگاهی که https://djangogirls.org روی آن ذخیره شده) نیاز است تا ما درخواستی (request) را از طریق دستگاه‌های بسیار زیادی ارسال کنیم. + +شبیه به این: + +![تصویر 1.3](images/internet_2.png) + +تصور کنید که وقتی شما https://djangogirls.org را تایپ می‌کنید، نامه‌ای فرستاده اید به این مضمون: "دختران جنگو عزیز، من می‌خواهم وب سایت djangogirls.org را ببینم. لطفاً آن را برای من بفرستید!" + +نامه شما به نزدیکترین اداره پست فرستاده می‌شود. بعد به اداره پست دیگری می‌رود که کمی بیشتر به مقصد نزدیک است و همینطور پیش می‌رود تا به مقصد نهایی برسد. تنها ویژگی این سیستم این است که اگر نامه های بسیاری به یک مقصد بفرستید (*data packets*) آن‌ها می‌توانند از مسیرهایی کاملاً متفاوت (*routers*) به مقصد برسند. این موضوع بستگی به این دارد که نامه ها در هر اداره پست چطور تقسیم شوند. + +![تصویر 1.4](images/internet_4.png) + +این روش کار است - شما پیغامی میفرستید و منتظر پاسخ می‌مانید. به جای قلم و کاغذ شما از بایت‌های داده استفاده می‌کنید اما منطق کار یکسان است! + +به جای آدرس یا نام خیابان، شهر و کدپستی، ما از آدرس IP استفاده می‌کنیم. کامپیوتر شما ابتدا از DNS (Domain Name System) می‌خواهد که djangogirls.org را به IP address تبدیل کند. این سیستم شبیه دفترچه تلفن‌های قدیمی است که شما می‌توانستید دنبال نام یک نفر بگردید و آدرس و شماره تلفن وی را پیدا کنید. + +وقتی شما نامه‌ای می‌فرستید نیاز است که ویژگی های مشخصی داشته باشد تا قابل ارسال باشد: آدرس، تمبر و غیره. علاوه بر این از زبانی استفاده می‌کنید که گیرنده آن را متوجه شود، درست است؟ عین همین اتفاق برای *data packet* هایی می‌افتد که شما برای دیدن یک وبسایت ارسال می‌کنید. ما از پروتکلی به نام HTTP (Hypertext Transfer Protocol) استفاده می‌کنیم. + +بنابراین به طور اصولی، وقتی شما وبسایتی دارید، نیاز است تا یک *سرور* داشته باشید که وبسایت بر روی آن قرار داشته باشد. وقتی که *سرور* یک *ریکوئست* (یک درخواست به صورت یک نامه) را دریافت می‌کند، وبسایت شما را در پاسخ به آن نامه ارسال می‌کند (در یک نامه جداگانه). + +از آنجاییکه این دوره آموزشی جنگو است، ممکن است شما بپرسید جنگو چه کاری را انجام می‌دهد. وقتی شما پاسخ هر درخواست را می‌فرستید، معمولاً نمی‌خواهید یک پاسخ یکسان را برای همه بفرستید. بسیار بهتر خواهد بود اگر هر نامه‌ای شخصی و ویژه هر فرد فرستنده، پاسخ داده شود، درست است؟ جنگو به شما کمک می‌کند تا این نامه‌های شخصی و جالب را بسازید. :) + +صحبت بس است - وقت ساختن است! \ No newline at end of file diff --git a/fa-IR/html/README.md b/fa-IR/html/README.md new file mode 100644 index 00000000000..8dc4c605f52 --- /dev/null +++ b/fa-IR/html/README.md @@ -0,0 +1,227 @@ +# آشنایی با HTML + +ممکن است بپرسید تمپلیت چیست؟ + +تمپلیت (به معنی قالب) فایلی است که می‌توانیم بارها از آن استفاده کنیم و اطلاعات مختلفی را به کمک آن و در یک فرمت ثابت ارائه کنیم. مثلاً شما می‌توانید از یک تمپلیت کمک بگیرید و یک نامه بنویسید چرا که با اینکه هر نامه‌ای پیغام و آدرس متفاوتی دارد، اما از فرمت مشابهی استفاده می‌کند. + +یک تمپلیت جنگو توسط زبانی به نام HTML تعریف می‌شود (همان HTML که در بخش اول، **اینترنت چگونه کار می‌کند**، به آن اشاره کرده بودیم). + +## HTML چیست؟ + +HTML نوعی از کد است که توسط مرورگر وب، مانند کروم و فایرفاکس یا سافاری، تفسیر و اجرا می‌شود تا یک صفحه وب را نشان دهد. + +HTML مخفف عبارت "HyperText Markup Language" است. **HyperText** به این معنی است که نوعی از نوشته است که هایپرلینک بین صفحات را پشتیبانی می‌کند. **Markup** یعنی ما یک متن را برمی‌داریم و آن را علامت گذاری می‌کنیم تا به سیستم دیگری (مثلاً در اینجا مرورگر وب) بگوییم چطور آن را تفسیر کند. کدهای HTML با **tag** ها ساخته شده اند که هرکدام با `>` آغاز و با `<` پایان می‌یابند. این تگ‌ها **المان‌های** نشانه گذاری هستند. + +## اولین تمپلیت شما! + +ساختن یک تمپلیت یعنی ساختن یک فایل تمپلیت. هرچیزی، یک فایل است، درست است؟ احتمالاً تا الان این موضوع را متوجه شده اید. + +تمپلیت‌ها در دایرکتوری `blog/templates/blog` ذخیره می‌شوند. بنابراین اول یک دایرکتوری به نام `templates` در دایرکتوری وبلاگ بسازید. سپس دایرکتوری دیگری به نام `blog` در داخل آن بسازید: + + blog + └───templates + └───blog + + +(ممکن است فکر کنید که چرا دوتا دایرکتوری به نام `blog` لازم داریم. همانطور که بعدتر خواهیم دید این یک سیستم نامگذاری کارآمد برای وقتی است که اوضاع پیچیده‌تر می‌شود.) + +حالا یک فایل `post_list.html` (که فعلاً خالی باشد) در دایرکتوری بسازید `blog/templates/blog`. + +نگاه کنید که الان وبسایت شما چه شکلی شده است: http://127.0.0.1:8000/ + +> اگر هنوز پیغام خطا `TemplateDoesNotExist` را می‌بینید، یک بار سرور را قطع و بعد دوباره فعال کنید. به خط فرمان بروید سرور را با زدن Ctrl+C (کلید کنترل و کلید C باهم) قطع کنید و با اجرای دستور `python manage.py runserver` مجدداً فعال کنید. + +![تصویر 11.1](images/step1.png) + +پیغام خطایی نیست! تبریک :) با اینحال وبسایت شما هنوز چیزی به غیر از یک صفحه خالی نشان نمی‌دهد برای اینکه تمپلیت شما خالی است. لازم است که آن را اصلاح کنیم. + +فایل جدید را در ویرایشگر کد باز کنید و موارد زیر را به آن اضافه کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +الان وبسایت شما چطور به نظر می‌رسد؟ به آن سری بزنید تا بفهمید: http://127.0.0.1:8000/ + +![تصویر 11.2](images/step3.png) + +کار می‌کند! خوب شد! :) + +* خط `` یک تگ HTML نیست. این عبارت فقط نوع فایل را مشخص می‌کند. در اینجا این عبارت به مرورگر اعلام می‌کند که نوع فایل [HTML5](https://html.spec.whatwg.org/#the-doctype) است. همیشه شروع هر نوع فایل HTML5 با همین عبارت شروع می‌شود. +* `` پایه‌ای‌ترین تگ و معمولاً اولین تگ در ابتدای صفحه است و تگ `` معمولاً در انتهای صفحه می‌آید. همانطور که می‌بینید، تمام محتوای وبسایت بین تگ `` در ابتدا و تگ `` در انتها قرار می‌گیرند +* تگ `

` برای پاراگراف‌ها به کار می‌رود و تگ `

` پایان هر پاراگراف را مشخص می‌کند + +## Head and body + +هر صفحه HTML همچنین به دو بخش اصلی تقسیم می‌شود: **head** و **body**. + +* **head** عنصری است که شامل اطلاعاتی در مورد هر فایل می‌شود که در صفحه نشان داده نمی‌شوند. + +* **body** عنصری است که شامل هر چیزی است که در صفحه وبسایت نمایش داده می‌شوند. + +ما از `` استفاده می‌کنیم تا در مورد تنظیمات فایل به مرورگر اطلاعاتی بدهیم و `` نشان می‌دهد که چه چیزی واقعاً در صفحه وجود دارد. + +برای مثال شما می‌توانید تگ عنوان یا title را به شکل زیر در ``، قرار دهید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +این فایل‎ را ذخیره کنید و وبسایت خود را دوباره بارگذاری کنید. + +![تصویر 11.3](images/step4.png) + +توجه کنید که چگونه مرورگر متوجه شد که "Ola's blog" عنوان صفحه شماست؟ مرورگر عبارت `Ola's blog` را تفسیر کرده و آن را به عنوان نام صفحه، در نوار نام صفحه مرورگر قرار داده است (البته عنوان در جاهای دیگری مانند bookmark کردن هم استفاده می‌شود). + +احتمالاً تا الان توجه کرده‌اید که هر تگ شروع به همراه یک *تگ پایان* و علامت `/` می‌آید و عوامل در آن نیز *nested* می‌شوند (یعنی شما نمی‌توانید یک تگ را ببندید مگر آنکه تمام تگ‌های درون آن را بسته باشید). + +شبیه گذاشتن چیزها در جعبه است. شما یک جعبه بزرگ دارید، ``؛ درون آن یک جعبه دیگر ``، و این همینطور ادامه دارد تا به کوچکترین جعبه برسد: `

`. + +شما باید از این قوانین *بستن تگ‌ها* و نیز *nesting*، پیروی کنید. اگر این قوانین رعایت نشوند مرورگر ممکن است نتواند فایل شما را درست تفسیر کند و صفحه HTML درست نمایش داده نخواهد شد. + +## تنظیم کردن تمپلیت + +الان می‌توانید کمی تفریح کنید و تلاش کنید تا تمپلیت خود را تنظیم کنید! در اینجا تعدادی تگ مفید معرفی شده: + +* `

heading

` یک تیتر برای عنوان‌های مهم +* `

sub-heading

` یک تیتر برای عنوان‌های کم اهمیت‌تر +* `

sub-sub-heading

` یک زیر عنوان که تا `
` درجه اهمیت آن کمتر می‌شود +* `

پاراگراف

پاراگرافی از نوشته‌ها` +* `تاکید` بر نوشته شما تاکید می‌کند +* `تاکید` تاکید بیشتر روی متن +* `
` به خط بعد می‌رود (شما نمی‌توانید چیزی درون تگ br بگذارید و علاوه بر این br، تگِ پایانی ندارد) +* `لینک` یک لینک می‌سازد +* `
  • آیتم اول
  • آیتم دوم
` یک لیست، دقیقاً مانند همین لیست درست می‌کند! +* `
` یک بخش جدید در صفحه تعریف می‌کند +* `` مجموعه‌ای از لینک‌های دسترسی را تعریف می‌کند +* `
`محتوای مستقل و فارق از محیط را مشخص می‌کند +* `
` یک بخش را در فایل مشخص می‌کند +* `
` بخش سربرگ یک صفحه را مشخص می‌کند +* `
` بخش محتوای اصلی صفحه را مشخص می‌کند +* `` محتوای جانبی نسبت به جایی که در آن قرار گرفته را مشخص می‌کند (مانند منوی کناری) +* `
` بخش پاورقی یک سند را مشخص می‌کند +* `` بک زمان (یا تاریخ و زمان) را مشخص می‌کند + +اینجا نمونه‌ای از یک تمپلیت کامل داریم. آن را در فایل `blog/templates/blog/post_list.html` کپی کنید: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +ما اینجا یک بخش `header` و دو بخش 0>article ایجاد کردیم. + +* بخش `header` شامل عنوان مقاله وبلاگ ماست - یک عنوان و یک لینک +* دو عنصر `article` شامل پست‌های وبلاگ ما به همراه تاریخ انتشار در یک عنصر `time`، یک عنصر`h2` با عنوان مقاله که قابل کلیک کردن است و عنصر `p` (paragraph) که برای متن مقاله استفاده شده است. + +چنین نتیجه ای به ما می‌دهد: + +![تصویر 11.4](images/step6.png) + +واای! ولی تا اینجا تمپلیت ما دقیقاً **اطلاعات یکسانی** را نمایش می‌دهد درحالیکه قبل‌تر در مورد این صحبت کردیم که تمپلیت به ما اجازه می‌دهد **اطلاعات متفاوتی** را در **قالب یکسان** نمایش دهیم. + +آن چیزی که واقعاً می‌خواهیم این است که پست‌های واقعی که در جنگو ادمین اضافه کرده‌ایم را نمایش دهد و این همان چیزی است که در ادامه سراغ آن خواهیم رفت. + +## فقط یک چیز دیگر: دیپلوی! + +خیلی خوب خواهد بود که همه اینها را به صورت آنلاین بر روی اینترنت ببینیم، درست است؟ پس بیایید یک بار دیگر به کمک PythonAnywhere وبسایت را منتشر کنیم: + +### کامیت کنید و کد را بر روی گیتهاب پوش کنید + +اول از همه ببینیم کدام فایل ها را به نسبت آخرین انتشار، تغییر داده ایم (این دستور را بر روی کامپیوتر خود اجرا کنید و نه در PythonAnywhere): + +{% filename %}خط فرمان{% endfilename %} + + $ git status + + +مطمئن باشید که در دایرکتوری `djangogirls` هستید و به `گیت` اجازه دهید تمام تغییرات ایجاد شده در این دایرکتوری را در نظر بگیرد: + +{% filename %}خط فرمان{% endfilename %} + + $ git add . + + +قبل از آنکه همه فایل‌ها را آپلود کنیم بگذارید ببینیم که `گیت` چه فایل‌هایی را آپلود خواهد کرد (تمام فایل‌هایی که `گیت` آپلود خواهد کرد الان سبز رنگ دیده می‌شوند): + +{% filename %}خط فرمان{% endfilename %} + + $ git status + + +حالا وقت آن است که بگوییم تمام این تغییرات را در سابقه خودش ذخیره کند. الان می‌خواهیم یک "commit message" یا پیغام کامیت تعریف کنیم که تغییرات ما را توضیح می‌دهد. هرچیزی که دلتان بخواهد می‌توانید تایپ کنید، اما بهتر است توضیحاتی را بنویسید که بعداً متوجه شوید در این مرحله چه تغییراتی داده‌اید. + +{% filename %}خط فرمان{% endfilename %} + + $ git commit -m "Changed the HTML for the site." + + +> **نکته** مطمئن باشید که از علامت نقل قول دوتایی در اطراف پیغام مربوط به کامیت استفاده کنید. + +وقتی این کار را انجام دادیم تغییرات را در گیتهاب آپلود (push) می‌کنیم: + +{% filename %}خط فرمان{% endfilename %} + + $ git push + + +### فایل‌های جدیدتان را بر روی PythonAnywhere ببرید و صفحه وبسایت را دوباره بارگذاری کنید + +* سپس دوباره به صفحه **Bash console** خود در [PythonAnywhere](https://www.pythonanywhere.com/consoles/) بروید (یا یک کنسول خط فرمان جدید باز کنید) و دستورات زیر را اجرا کنید: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +یادتان باشد که `` را با زیر دامنه اصلی خود در PythonAnywhere عوض کنید البته بدون آکولادها. نام زیردامنه شما معمولاً همان نام کاربری شما در PythonAnywhere است اما در مواردی ممکن است کمی متفاوت باشد (مثلاً اگر نام کاربری شما دارای حروف بزرگ باشد). اگر این دستور کار نکرد از `ls` (لیست کردن فایل‌ها) استفاده کنید تا زیردامنه خود را پیدا کنید و سپس با دستور `cd` به آن دایرکتوری بروید. + +حالا منتظر شوید تا فایل‌های شما دانلود شوند. اگر می‌خواهید بدانید که فایل‌ها رسیده اند یا نه به صفحه **"Files"** بروید و کدهای خود بر روی PythonAnywhere را ببینید (شما میتوانید به بقیه فایل‌های خود در PythonAnywhere، از طریق کلید منو در کنسول دسترسی پیدا کنید). + +* سرانجام به صفحه ["Web"](https://www.pythonanywhere.com/web_app_setup/) بروید و **Reload** را بزنید. + +تغییرات شما آنلاین شده اند! صفحه وبسایت خود را در مرورگرتان دوباره بارگذاری کنید. تغییرات دیده خواهند شد. :) \ No newline at end of file diff --git a/fa-IR/installation/README.md b/fa-IR/installation/README.md new file mode 100644 index 00000000000..4857ed957d7 --- /dev/null +++ b/fa-IR/installation/README.md @@ -0,0 +1,68 @@ +# اگر این آموزش را در خانه دنبال می‌کنید + +اگر این آموزش را در خانه دنبال می‌کنید و نه در یکی از [رویدادهای دختران جنگو](https://djangogirls.org/events/)، می‌توانید به طور کامل از این بخش بگذرید و به بخش [اینترنت چگونه کار می‌کند](../how_the_internet_works/README.md) بروید. + +به دلیل اینکه ما نصب کردن هر چیزی را که دراین سری آموزشی نیاز است، در محل مورد نیاز بیان می‌کنیم. این صفحه تنها برای بیان همه دستورات نصب در یک مکان، اضافه شده است (که برای برخی کارگاه‌ها مفید است). شما می‌توانید هرچیزی که در این بخش آمده است را نصب کنید. اما اگر ترجیح می‌دهید پیش از نصب چند ابزار و نرم افزار روی کامپیوترتان، در مورد آن‌ها یاد بگیرید، از این بخش عبور کنید. ما نحوه‌ی نصب هر چیزی را، زمانی که به آن نیاز داشتید، توضیح می‌دهیم. + +موفق باشید! + +# اگر در یک کارگاه شرکت کرده‌اید + +اگر در یکی از [رویدادهای جنگو برای دختران](https://djangogirls.org/events/) شرکت کرده اید: + +* ممکن است کارگاه شما یک "جلسه نصب پیش‌نیازها" قبل از رویداد اصلی داشته باشد. اگر در جلسه نصب پیش‌نیازها هستید، این بخش مخصوص شماست! برای نصب هرچیزی که در این رویداد نیاز دارید، دستورالعمل‌های این بخش را دنبال کنید، و در صورت نیاز از مربی‌ها کمک بگیرید. سپس در کارگاه اصلی، می‌توانید از دستورالعمل‌های نصب که در آموزش اصلی با آنها مواجه می‌شوید، عبور کنید. +* ممکن است برگزار کنندگان کارگاه، از شما بخواهند تا سعی کنید همه چیز را قبل از شروع کارگاه روی کامپیوترتان نصب کنید. اگر از شما این درخواست را داشته اند، این بخش برای شماست! به بهترین نحو دستورالعمل های این بخش را دنبال کنید. اگر نتوانستید چیزی را نصب کنید، در کارگاه اصلی، زمانی که به دستورالعمل‌های نصب آن بخش در آموزش اصلی می‌رسید، می‌توانید از مربی‌ها کمک بگیرید. +* اگر کارگاه شما فاقد جلسه نصب پیش نیازها بود (یا شما نتوانستید در آن شرکت کنید)، و اگر برگزارکنندگان از شما نخواستند که همه چیز را پیش از شروع رویداد نصب کنید، از این بخش عبور کنید و مستقیم به بخش [ اینترنت چگونه کار می‌کند](../how_the_internet_works/README.md) بروید. شما هر چیزی را که به آن نیاز دارید، در طول آموزش اصلی نصب خواهید کرد. + +# نصب پیش‌نیازها + +در این آموزش شما یک وبلاگ خواهید ساخت. برای انجام این کار، در خلال روند آموزش، به شما نحوه‌ی نصب نرم‌افزارهای مختلف روی کامپیوترتان و نحوه‌ی راه اندازی چند حساب اینترنتی گفته خواهد شد. این بخش شامل تمام مراحل نصب و دستورالعمل‌های ثبت نام است (که برای بعضی از کارگاه‌ها مفید است). + + {% include "/chromebook_setup/instructions.md" %} + + + +# معرفی کوتاه کنسول خط فرمان {#command-line} + +بسیاری از مراحل زیر به "کنسول"، "ترمینال"، "پنجره دستورات" یا "خط فرمان" اشاره می‌کنند ـ همه آنها یک معنا دارند: یک پنجره روی کامپیوتر شما که می‌توانید دستوراتی را در آن وارد کنید. زمانی که به آموزش اصلی رسیدید، در مورد خط فرمان بیشتر می‌آموزید. فعلاً، اصلی‌ترین موردی که باید بدانید نحوه باز کردن یک پنجره خط فرمان و شکل ظاهری آن است: {% include "/intro_to_command_line/open_instructions.md" %} + +# نصب پایتون {#python} + +{% include "/python_installation/instructions.md" %} + +# نصب یک ویرایشگر متنی {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# نصب محیط مجازی و نصب جنگو {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# نصب گیت {#git} + +{% include "/deploy/install_git.md" %} + +# ساخت حساب کاربری GitHub {#github-account} + +به [GitHub.com](https://www.github.com) بروید و برای یک حساب کاربری جدید و رایگان،‌ ثبت نام کنید. از بخاطر سپردن رمز عبور خود اطمینان حاصل کنید (اگر از یک نرم افزار مدیریت رمزهای عبور استفاده میکنید، رمز عبور جدید را به آن اضافه کنید). + +# ساخت حساب کاربری PythonAnywhere {#pythonanywhere-account} + +{% include "/deploy/signup_pythonanywhere.md" %} + +# شروع کنید و آموزش‌ها را بخوانید + +تبریک، شما کاملاً آماده شروع هستید. اگر هنوز پیش از شروع کارگاه زمان دارید، خواندن بخش‌های ابتدایی برایتان مفید خواهد بود: + +* [اینترنت چگونه کار می‌کند](../how_the_internet_works/README.md) + +* [معرفی خط‌فرمان](../intro_to_command_line/README.md) + +* [معرفی پایتون](../python_introduction/README.md) + +* [جنگو چیست؟](../django/README.md) + +# از کارگاه لذت ببرید! + +زمانی که کارگاه را شروع کردید، می‌توانید مستقیماً به بخش [اولین پروژه جنگو شما](../django_start_project/README.md) بروید، چون قبلاً مطالب بخش‌های پیش از آن را مرور کرده اید. \ No newline at end of file diff --git a/fa-IR/intro_to_command_line/README.md b/fa-IR/intro_to_command_line/README.md new file mode 100644 index 00000000000..4ee16eb9ab3 --- /dev/null +++ b/fa-IR/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# آشنایی با خط فرمان + +> برای خوانندگان در خانه: این فصل در ویدئو [دوست جدید شما: Command Line](https://www.youtube.com/watch?v=jvZLWhkzX-8) توضیح داده شده است. + +هیجان انگیز است! شما تا چند دقیقه دیگر اولین خط کد خود را خواهید نوشت! :) + +**بگذارید شما را به اولین دوست جدیدتان معرفی کنیم: خط فرمان!** + +این مراحل به شما یاد می‌دهد که چطور از این پنجره سیاهی استفاده کنید که همه هکرها از آن استفاده می‌کنند. ممکن است در ابتدا کمی ترسناک به نظر بیاید ولی این فقط یک علامت است که نشان می‌دهد سیستم منتظر فرمان‌های شماست. + +> **نکته** توجه داشته باشید که در این دوره آموزشی ما بارها از دایرکتوری یا پوشه صحبت کرده ایم هر دو این مفاهیم یکی هستند. + +## خط فرمان چیست؟ + +این پنجره که معمولاً **command line** یا **صفحه خط فرمان** گفته می‌شود یک نرم افزار مبتنی بر متن است که برای مشاهده، مدیریت و تغییر فایل‌ها از آن استفاده می‌شود. شباهت زیادی به ویندوز اکسپلورر یا فایندر در مک دارد با این تفاوت که اینترفیس گرافیکی ندارد. نام های دیگر خط فرمان این‌ها هستند: *cmd*, *CLI*, *prompt*, *console* ، *terminal*. + +## اینترفیس خط فرمان را باز کنید + +برای اینکه کمی تجربه کنیم باید ابتدا اینترفیس خط فرمان را باز کنید. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## Prompt + +شما صفحه‌ای سیاه یا سفید خواهید دید که منتظر دستورات شماست. + + + +اگر بر روی مک یا لینوکس کار می‌کنید، ممکن است یک علامت `$` ببینید: + +{% filename %}خط فرمان{% endfilename %} + + $ + + + + + + +بر روی ویندوز، احتمالاً علامت `>` را خواهید دید: + +{% filename %}خط فرمان{% endfilename %} + + > + + +به بخش لینوکس در بالا نگاه کنید، چیزی که در آنجا می‌بینید بسیار شبیه چیزی است که در وبسایت PythonAnywhere و در ادامه این دوره آموزشی خواهید دید. + + + +هر دستور با یک پیشوند `$` یا `>` و یک اسپیس نشان داده شده‌اند، ولی شما نباید آن‌ها را تایپ کنید کامپیوتر آن را قبل از هر دستور شما گذاشته است. :) + +> یک نکته کوچک: ممکن است در کامپیوتر شما چیزهایی شبیه به `C:\Users\ola>` یا `Olas-MacBook-Air:~ ola$` قبل از علامت پرامت باشد که کاملاً طبیعی است. + +به بخشی که از ابتدای خط تا علامت `$` یا `>` را شامل می‌شود *command line prompt* یا به طور خلاصه *prompt* گفته می‌شود (prompt به معنی تشویق کردن و برانگیختن است). این علامت شما را تشویق می‌کند تا جلوی آن چیزی بنویسید. + +در این دوره آموزشی وقتی که از شما می‌خواهیم که دستوری را بنویسید، معمولاً در سمت چپ آن `$` یا `>` را گذاشته‌ایم. این تکه را در نظر نگیرید و فقط دستور را که بلافاصله بعد از پرامت قرار دارد تایپ کنید. + +## اولین دستور شما (وای!) + +بیایید با تایپ این دستور شروع کنیم: + + + +{% filename %}خط فرمان{% endfilename %} + + $ whoami + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > whoami + + + + +و سپس کلید `enter` را بزنید. نتیجه این خواهد بود: + +{% filename %}خط فرمان{% endfilename %} + + $ whoami + olasitarska + + +همانطور که می‌بینید کامپیوتر نام کاربری شما را نشان می‌دهد. جالب نیست؟ :) + +> برای امتحان کردن هر دستور آن را کپی نکیند. با تایپ کردن بهتر یاد خواهید گرفت! + +## اصول اولیه + +هر سیستم عامل، مجموعه دستورات کمی متفاوت برای خط فرمان، با دیگر سیستم عامل‌ها دارد، بنابراین مطمئن شوید که دستورالعمل‌های سیستم عامل خود را دنبال می‌کنید. حالا این را امتحان کنیم، آماده اید؟ + +### دایرکتوری جاری + +بسیار خوب است که بفهمیم در کدام دایرکتوری هستیم. این دستور را تایپ کنید و کلید `enter` را بزنید: + + + +{% filename %}خط فرمان{% endfilename %} + + $ pwd + /Users/olasitarska + + +> نکته: 'pwd' مخفف 'print working directory' به معنی 'دایرکتوری در حال اجرا را چاپ کن' است. + + + + + +{% filename %}خط فرمان{% endfilename %} + + > cd + C:\Users\olasitarska + + +> نکته: 'cd' مخفف 'change directory' به معنی 'دایرکتوری را عوض کن'. در نرم افزار PowerShell در ویندوز شما می‌توانید مانند لینوکس یا مک از دستور pwd استفاده کنید. + + + +احتمالاً چیزی شبیه به این را بر روی کامپیوتر خود دیده اید. وقتی پنچره خط فرمان را باز می‌کنید معمولاً در دایرکتوری home اکانت کاربری خود هستید. + +* * * + +### چیزهای بیشتر در مورد یک فرمان + +بسیاری از فرمان‌هایی که شما می‌توانید در پرامت فرمان تایپ کنید یک راهنمای داخلی دارند که می‌توانید آن را ببینید و بخوانید! مثلاٌ برای آنکه در مورد فرمان دایرکتوری جاری بیشتر بدانید: + + + +OS X و لینوکس یک فرمان `man` دارند که در مورد فرمان‌ها کمک زیادی می‌کند. دستور `man pwd` را امتحان کنید و ببینید که چه می‌شود. یا دستور `man` را قبل از فرمان‌های دیگر قرار دهید تا راهنمای داخلی آن‌ها را ببینید. خروجی فرمان `man` صفحه بندی شده است. با کمک کلید اسپیس به صفحه بعد بروید و با زدن `q` از راهنما خارج شوید. + + + + + +اضافه کردن یک پسوند `/?` به اکثر فرمان‌ها باعث می‌شود که صفحه راهنما نشان داده شود. لازم است صفحه را به سمت بالا اسکرول کنید تا تمام آن را ببینید. `cd /?` را امتحان کنید. + + + +### لیست کردن فایل‌ها و دایرکتوری‌ها + +چی توش هست؟ خوبه که بفهمیم. نگاه کنید: + + + +{% filename %}خط فرمان{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> نکته: در PowerShell شما می‌توانید مانند لینوکس یا Mac OS X از دستور 'ls' استفاده کنید. + +* * * + +### تغییر دایرکتوری جاری + +حالا به دایرکتوری Desktop کامپیوترمان برویم: + + + +{% filename %}خط فرمان{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}خط فرمان{% endfilename %} + + $ cd Desktop + + +توجه داشته باشید که ممکن است دایرکتوری Desktop به زبان کاربری تعیین شده در لینوکس شما ترجمه شود. اگر چنین اتفاقی افتاد لازم است که شما `Desktop` را با نام ترجمه شده عوض کنید؛ مثلاً برای زبان آلمانی با `Schreibtisch` عوض کنید. + + + + + +{% filename %}خط فرمان{% endfilename %} + + > cd Desktop + + + + +بررسی کنید که آیا واقعاً دایرکتوری جاری عوض شد: + + + +{% filename %}خط فرمان{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +بله درست شد! + +> نکته حرفه‌ای: اگر شما تایپ کنید `cd D` و بعد کلید `tab` را بر روی کیبورد بزنید، خط فرمان ادامه فرمان شما را تایپ خواهد کرد بنابراین سریعتر می‌توانید حرکت کنید. اگر دایرکتوری هایی که با "D" شروع می‌شوند بیشتر از یکی باشند، با دوبار زدن کلید `tab` لیستی از آن‌ها را خواهید دید. + +* * * + +### ساختن دایرکتوری + +چطور است که یک دایرکتوری آزمایشی بر روی دسکتاپ بسازیم؟ به این روش می‌توانید انجام دهید: + + + +{% filename %}خط فرمان{% endfilename %} + + $ mkdir practice + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > mkdir practice + + + + +این دستور کوچک یک دایرکتوری به نام `practice` بر روی دسکتاپ شما خواهد ساخت. شما می‌توانید با اجرا کردن دستور `ls` یا `dir` بررسی کنید که آیا این دایرکتوری روی Desktop هست یا نه! آن را امتحان کنید. :) + +> نکته حرفه‌ای: اگر دوست ندارید یک دستور را بارها و بارها تایپ کنید، کلید `up arrow` یا جهت بالا و `down arrow` یا جهت پایین را بر روی کیبورد بزنید تا فرمان‌هایی که اخیراً زده اید را ببینید. + +* * * + +### تمرین! + +یک چالش کوچک برای شما: در این دایرکتوری `practice` که اخیراٌ ساخته اید، یک دایرکتوری به نام `test` بسازید. (از دستور `cd` و `mkdir` استفاده کنید.) + +#### راه حل: + + + +{% filename %}خط فرمان{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +تبریک! :) + +* * * + +### پاک‌سازی + +نمی‌خواهیم همه جا را شلوغ کنیم، پس بیایید همه چیزهایی که ساخته ایم را پاک کنیم. + +اول از همه باید به Desktop برویم: + + + +{% filename %}خط فرمان{% endfilename %} + + $ cd .. + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > cd .. + + + + +استفاده کردن از `..` به همراه دستور `cd` باعث خواهد شد که به دایرکتوری parent بروید (parent دایرکتوری است که دایرکتوری جاری درون آن قرار دارد). + +بررسی کنید که کجا هستید: + + + +{% filename %}خط فرمان{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +حالا وقت پاک کردن دایرکتوری `practice` است: + +> **توجه**: پاک کردن فایل‌ها با `del` یا `rmdir` یا `rm` غیر قابل بازگشت است به این معنی که *فایل‌های پاک شده برای همیشه از بین می‌روند*! بنابراین هنگام کار با این دستورها بسیار احتیاط کنید. + + + +{% filename %}خط فرمان{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +انجام شد! برای اینکه مطمئن شوید پاک شده است آن را چک کنید: + + + +{% filename %}خط فرمان{% endfilename %} + + $ ls + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > dir + + + + +### خروج + +برای الان کافی است! شما می‌توانید به راحتی خط فرمان را ببندید. بیایید به روش هکرها انجامش دهیم، باشه؟ :) + + + +{% filename %}خط فرمان{% endfilename %} + + $ exit + + + + + + +{% filename %}خط فرمان{% endfilename %} + + > exit + + + + +با حال بود، نه؟ :) + +## چکیده + +اینجا چکیده‌ای از دستورات مهم آورده شده: + +| دستورات (Windows) | دستورات (Mac OS / Linux) | توضیحات | مثال | +| ----------------- | ------------------------ | --------------------------- | -------------------------------------------------- | +| exit | exit | بستن پنجره خط فرمان | **exit** | +| cd | cd | تغییر دایرکتوری | **cd test** | +| cd | pwd | نشان دادن دایرکتوری جاری | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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** | +| rmdir (or del) | rm | حذف کردن یک فایل | **del c:\test\test.txt** | +| rmdir /S | rm -r | حذف کردن یک دایرکتوری | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | دیدن راهنمای یک دستور | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +این‌ها تعداد بسیار کمی از دستوراتی هستند که می‌توانید در خط فرمان اجرا کنید، اما امروز چیزی بیشتر از این‌ها لازم ندارید. + +اگر علاقمند هستید، وبسایت [ss64.com](http://ss64.com) مرجع کاملی از انواع فرمان‌ها برای سیستم عامل‌های مختلف دارد. + +## آماده هستید؟ + +حالا در پایتون شیرجه بزنیم! \ No newline at end of file diff --git a/fa-IR/intro_to_command_line/open_instructions.md b/fa-IR/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..e6aff14474a --- /dev/null +++ b/fa-IR/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +بسته به نسخه ویندوز و نیز نوع کیبورد شما، یکی از موارد زیر برای شما یک command window یا خط فرمان باز خواهد کرد (شاید باید کمی امتحان کنید ولی لازم نیست تمام این پیشنهادات را آزمایش کنید): + +- به منوی استارت یا screen بروید و عبارت "Command Prompt" را در بخش جستجو وارد کنید. +- این مسیر را دنبال کنید Start menu → Windows System → Command Prompt. +- این مسیر را دنبال کنید Start menu → All Programs → Accessories → Command Prompt. +- به بخش Start بروید و موس را روی صفحه تکان دهید و به گوشه پایین سمت چپ بروید و بر روی فلش به سمت پایین که ظاهر می‌شود کلید کنید (در یک سیستم تاچ اسکرین باید از پایین اسکرین را لمس کنید و دست خود را بالا بکشید). صفحه App ها باید باز شود. بر روی Command Prompt در بخش Windows System کلیک کنید. +- کلید مخصوص Windows را بر روی کیبورد نگه دارید و دکمه "X" را بزنید. "Command Prompt" را از پنجره‌ای که باز می‌شود انتخاب کنید. +- کلید Windows را نگه دارید و دکمه "R" را بزنید تا پنجره "Run" بازشود. تایپ کنید "cmd" و کلید OK را بزنید. + +![در پنجره "Run" بنویسید "cmd"](../python_installation/images/windows-plus-r.png) + +بعداً در این دوره آموزشی احتیاج دارید که دو پنجره خط فرمان به طور همزمان باز داشته باشید. با این حال در برخی نسخه‌های ویندوز، اگر یک پنجره خط فرمان باز داشته باشید و از همان روش برای باز کردن یک پنجره خط فرمان دیگری استفاده کنید به جای باز شدن پنجره جدید، همان قبلی دوباره نشان داده می‌شود. حالا روی کامپیوتر خود امتحان کنید و ببینید چه اتفاقی می‌افتد! اگر فقط یک پنجره خط فرمان دریافت کردید، یک روش دیگر از این لیست بالا را امتحان کنید. حداقل یکی از این‌ها باید یک پنجره جدید خط فرمان بازکند. + + + + + +به اینجا بروید Applications → Utilities → Terminal. + + + + + +احتمالاً Applications → Accessories → Terminal یا Applications → System → Terminal است که بستگی به سیستم کامپیوتر شما دارد. اگر در این آدرس‌ها پیدا نکردید سعی کنید با جستجو در گوگل جای آن را پیدا کنید. :) + + \ No newline at end of file diff --git a/fa-IR/python_installation/README.md b/fa-IR/python_installation/README.md new file mode 100644 index 00000000000..53720da3016 --- /dev/null +++ b/fa-IR/python_installation/README.md @@ -0,0 +1,15 @@ +# بیایید پایتون را شروع کنیم + +بالاخره به اینجا رسیدیم! + +اما در ابتدا بگذارید که به شما بگوییم پایتون چیست. پایتون یک زبان برنامه نویسی بسیار رایج است که می‌تواند برای ساخت وبسایت، بازی‌ها، نرم افزارهای علمی، گرافیک و بسیاری امور دیگر استفاده شود. + +پایتون به اواخر دهه 1980 باز می‌گردد و هدف اصلی آن این بود که زبانی طراحی شود که خواندن آن برای افراد هم راحت باشد (و نه اینکه صرفاً ماشین‌ها راحت باشند!). به خاطر همین است که خواندن آن نسبت به بقیه زبان‌ها ساده تر است، اما نگران نباشید، پایتون واقعاً قدرتمند است! + +# نصب و راه اندازی پایتون + +> **نکته** اگر از Chromebook استفاده می‌کنید، از این بخش رد شوید و دستورالعمل‌های بخش [نصب Chromebook](../chromebook_setup/README.md) را پیگیری کنید. +> +> **نکته** اگر مراحل [نصب و راه‌اندازی](../installation/README.md) را طی کرده‌اید، نیازی به انجام دوباره آن نیست. شما می‌توانید به بخش بعد بروید! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/fa-IR/python_installation/instructions.md b/fa-IR/python_installation/instructions.md new file mode 100644 index 00000000000..946d037a67b --- /dev/null +++ b/fa-IR/python_installation/instructions.md @@ -0,0 +1,117 @@ +> برای خوانندگان در خانه: این فصل در ویدئو [نصب پایتون و ویرایشگر کد](https://www.youtube.com/watch?v=pVTaqzKZCdA) توضیح داده شده است. +> +> این قسمت بر اساس دوره آموزشی Geek Girls Carrots نوشته شده است.(https://github.com/ggcarrots/django-carrots) + +جنگو با پایتون نوشته شده است. برای انجام هر کاری در جنگو، به زبان پایتون احتیاج داریم. بیایید با نصب پایتون شروع کنیم! ما می‌خواهیم شما آخرین نسخه پایتون 3 را نصب کنید، بنابراین اگر هرنسخه قدیمی تری دارید باید آن را به روزرسانی کنید. اگر پایتون نسخه {{ book.py_min_version }} یا بالاتر دارید، خوب است. + +حتی اگر بر روی کامپیوتر شما Anaconda نصب شده است، لطفاً پایتون معمولی را به روش زیر نصب کنید. + + + +ابتدا چک کنید که کامپیوتر شما دارای ویندوز 32-bit است یا 64-bit، در ردیف "System type" در صفحه System Info می‌توانید این را متوجه شوید. برای پیدا کردن این صفحه یکی از کارهای زیر را انجام دهید: + +* دکمه Windows و دکمه Pause/Break را همزمان روی کیبورد فشار دهید +* Control Panel را از منو ویندوز باز کنید، سپس به System & Security بروید و بعد از آن به System بروید +* دکمه Windows را فشار دهید، سپس مسیر Settings > System > About را دنبال کنید +* منوی Start ویندوز را برای یافتن "System Information" جستجو کنید. برای این کار بر روی منوی Start کلیک کنید یا کلید Windows را بزنید، سپس شروع به تایپ کردن `System Information` کنید. این کار باعث خواهد شد پیشنهادهای مختلف در هنگام تایپ کردن به شما نشان داده شود. شما می‌توانید گزینه System Information‌ را به محض ظاهر شدن، انتخاب کنید. + +می‌توانید پایتون برای ویندوز را از وبسایت https://www.python.org/downloads/windows/ دانلود کنید. بر روی لینک "Latest Python 3 Release - Python x.x.x" کلیک کنید. اگر کامپیوتر شما نسخه **64-bit** ویندوز را اجرا می‌کند، **Windows x86-64 executable installer** را دانلود کنید. در غیر اینصورت، **Windows x86 executable installer** را دانلود کنید. پس از دانلود کردن اینستالر، باید آن را اجرا کنید (بر روی آن دوبار کلیک کنید) و دستورالعمل‌ها را دنبال کنید. + +نکته قابل توجه: در هنگام نصب پنجره‌ای را خواهید دید به نام "Setup". مطمئن شوید که گزینه "Add Python {{ book.py_version }} to PATH" یا "Add Python to your environment variables"را انتخاب کرده‌اید و سپس بر روی "Install Now" که اینجا می‌بینید، کلیک کنید (اگر نسخه‌‌های دیگری را نصب کنید ممکن است کمی با این متفاوت باشد): + +![فراموش نکنید که پایتون را به Path اضافه کنید](../python_installation/images/python-installation-options.png) + +وقتی که نصب کامل شد، یک پنجره خواهید دید که شما را به یک لینک برای آموزش بیشتر در مورد پایتون و نیز در مورد نسخه‌ای که نصب کرده‌اید ارجاع می‌دهد. این پنجره را کنسل کنید و یا ببندید - شما در همین دوره آموزشی بیشتر در مورد پایتون یاد خواهید گرفت! + +نکته: اگر از نسخه‌های قدیمی‌تر ویندوز استفاده می‌کنید (7، Vista یا نسخه‌های قدیمی‌تر) و نصب پایتون نسخه {{ book.py_version }} با خطا مواجه شد، تمام آپدیت‌های ویندوز را نصب کنید و دوباره برای نصب پایتون تلاش کنید. اگر همچنان با خطا مواجه شدید، سعی کنید پایتون نسخه {{ book.py_min_release }} را از [Python.org](https://www.python.org/downloads/windows/) نصب کنید. + +> جنگو {{ book.django_version }} به پایتون {{ book.py_min_version }} یا بالاتر نیاز دارد که ویندوز XP یا نسخه‌های قدیمی‌تر را پشتیبانی نمی‌کند. + + + + + +> **نکته** قبل از نصب پایتون بر روی OS X، باید مطمئن شوید که تنظیمات Mac‌، اجازه نصب پکیج‌هایی را که در App Store‌ نیستند، می‌دهد. به System Preferences بروید (در پوشه Applications است)، بر روی "Security & Privacy," کلیک کنید و به تب "General" بروید. اگر "Allow apps downloaded from:" بر روی "Mac App Store" تنظیم شده بود آن را به گزینه "Mac App Store and identified developers" تغییر دهید. + +شما باید به آدرس https://www.python.org/downloads/mac-osx/ بروید و آخرین نسخه پایتون را دانلود کنید: + +* فایل *Mac OS X 64-bit/32-bit installer* را دانلود کنید، +* بر روی *python-{{ book.py_release }}-macosx10.9.pkg* دوبار کلیک کنید تا نصب‌کننده نرم‌افزار فعال شود. + + + + + +احتمال زیادی دارد که شما بر روی کامپیوترتان پایتون داشته باشید. برای چک کردن آنکه آیا پایتون دارید (یا اینکه نسخه آن چیست)، یک کنسول باز کنید و دستورات زیر را تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +اگر نسخه نصب شده دیگری از پایتون دارید حداقل {{ book.py_min_version }} (یا مثلاً {{ book.py_min_release }})، نیازی به به‌‌روزرسانی ندارید. اگر پایتون نصب شده ندارید یا نسخه دیگری را می‌خواهید، اول باید به کمک دستورات زیر، کنترل کنید که از کدام توزیع لینوکس استفاده می‌کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +سپس بسته به نتیجه، یکی از روش‌های نصب زیر را به کار ببرید. + + + + + +این دستور را در کنسول تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ sudo apt install python3 + + + + + + +این دستور را در کنسول تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ sudo dnf install python3 + + +اگر بر روی نسخه‌های قدیمی Fedora کار می‌کنید ممکن است پیغام خطایی بگیرید که `dnf` پیدا نشد. در این مورد، باید به جای آن از `yum` استفاده کنید. + + + + + +این دستور را در کنسول تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ sudo zypper install python3 + + + + +برای بررسی موفقیت‌آمیز بودن نصب، یک خط فرمان باز کنید و دستور `python3 + +

{% filename %}خط فرمان{% endfilename %}

+ +
$ python3 --version
+Python {{ book.py_release }}
+`
+ +نسخه نمایش داده شده ممکن است با {{ book.py_release }} متفاوت باشد اما باید آن چیزی باشد که در موقع نصب انتخاب کرده‌اید. + +**نکته:** اگر بر روی ویندوز کار می‌کنید و خطای `python3` wasn't found را گرفتید، از دستور `python` (بدون `3`) استفاده کنید و ببنید آیا ممکن است که نسخه پایتون {{ book.py_min_version }} یا بالاتر باشد. اگر این کار هم موثر نبود، یک خط فرمان جدید بازکنید و دوباره تلاش کنید؛ اگر خط فرمان شما از قبل از نصب پایتون باز مانده باشد ممکن است چنین خطایی دریافت کنید. + +* * * + +اگر جایی تردید داشتید یا مشکل دیگری بوجود آمد که نمی‌دانستید چه باید بکنید، لطفاً از مربی خود کمک بگیرید! گاهی وقت‌ها اوضاع به خوبی پیش نمی‌رود و بهتر است از فرد باتجربه‌تری کمک بگیرید. \ No newline at end of file diff --git a/fa-IR/python_introduction/README.md b/fa-IR/python_introduction/README.md new file mode 100644 index 00000000000..d476d7ab8c2 --- /dev/null +++ b/fa-IR/python_introduction/README.md @@ -0,0 +1,1071 @@ +{% set warning_icon = '' %} + +# آشنایی با پایتون + +> قسمت‌هایی از این بخش بر اساس دوره آموزشی Geek Girls Carrots طراحی شده است (https://github.com/ggcarrots/django-carrots). + +حالا بیایید کمی کد بنویسیم! + +## خط فرمان پایتون + +> > برای کسانی که در خانه مطالعه می‌کنند این بخش در ویدئو [Python Basics: Integers, Strings, Lists, Variables and Errors](https://www.youtube.com/watch?v=MO63L4s-20U) توضیح داده شده است. + +برای آنکه با پایتون کار کنیم باید یک کنسول *خط فرمان* روی کامپیوتر خود باز کنید. احتمالا بلد هستید که چطور این کار را بکنید، در بخش [آشنایی با خط فرمان](../intro_to_command_line/README.md) آن را یاد گرفته‌اید. + +زمانی که آماده بودید، دستورالعمل‌های زیر را دنبال کنید. + +ما می‌خواهیم یک کنسول پایتون باز کنیم، پس در کنسول خط فرمان ویندوز `python` و در ترمینال لینوکس/ مک `python3` را تایپ کنید و `enter` بزنید. + +{% filename %}خط فرمان{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## اولین دستور پایتونی شما! + +پس از اجرای دستور Python، خط فرمان به `>>>` تغییر می‌کند. این تغییر برای ما به معنای آن است که در حال حاضر فقط می‌توانیم از دستورات زبان پایتون استفاده کنیم. شما نیازی به تایپ `>>>` ندارید - خط فرمان پایتون این کار را برایتان میکند. + +اگر هر زمان قصد خروج از خط فرمان پابتون را داشتید `exit()` را تایپ کنید یا از `Ctrl + Z` در ویندوز و `Ctrl + D` در مک/لینوکس استفاده کنید. پس از خروج `>>>` را دیگر نمی‌بینید. + +ما الان نمی‌خواهیم از خط فرمان پایتون خارج شویم. ما می‌خواهیم چیزهای بیشتری در مورد آن یاد بگیریم. بیایید با کمی ریاضیات شروع کنیم، مانند `2 + 3`3 و زدن `enter`. + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +خوبه! دیدید که جواب چگونه ظاهر شد؟ پایتون ریاضیات را می‌فهمد! می‌توانید دستور دیگری مثل این را امتحان کنید: + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +برای اجرای محاسبات نمایی، مانند ۲ به توان ۳، تایپ میکنیم: {% filename %}خط فرمان{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +کمی با دستورات مختلف محاسباتی تفریح کنید و دوباره آموزش را ادامه دهید. :) + +همانطور که می‌بینید، پایتون محاسبه‌گر بسیار خوبی است. آیا به این فکر می‌کنید که چه کارهای دیگری می‌شود انجام داد… + +## رشته‌های متنی + +چطور است با اسم شما شروع کنیم؟ نام خود را بین علامت نقل قول به صورت زیر بنویسید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> "Ola" +'Ola' +``` + +شما همین الان اولین رشته متنی خود را ساختید! رشته متنی دنباله‌ای از کاراکترها است که می‌توان آن‌ها را توسط کامپیوتر پردازش کرد. رشته متنی همواره باید با یک علامت شروع، و با همان پایان یابد. این علامت ممکن است نقل قول تکی یا آپاستروف (`'`) یا نقل قول دوتایی (`"`) باشد (در پایتون بین این دو فرقی نیست) این علامت ها به پایتون میگویند که حاوی یک رشته متنی هستند. + +رشته ها می‌توانند به همدیگر الحاق شوند. دستور زیر را امتحان کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +همچنین میتوانید یک رشته را در یک عدد ضرب کنید، رشته به تعداد آن عدد تکرار می‌شود: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +اگر نیاز داشتید تا یک علامت آپاستروف داخل رشته بیاورید، دو راه دارید. + +استفاده از علامت نقل قول دوتایی: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +یا استفاده از یک بک اسلش (``) پیش از علامت آپاستروف: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +خوب است، نه؟ برای دیدن نام خود با حروف بزرگ، تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +شما همین الان از **متد** `upper` روی رشته متنی استفاده کردید! یک متد (مانند `upper()`) دنباله‌ای از دستورات پایتونی است. زمانی که متد را صدا بزنید، آن دستورات روی یک شی ورودی (`"Ola"`) اعمال می‌شود. + +آیا می‌خواهید تعداد حروف نام خود را بدانید؟ یک **تابع** برای این کار هم هست! + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +به این فکر می‌کنید که چرا گاهی تابع را با یک `.` در انتهای یک رشته صدا می‌کنیم (مانند `"Ola".upper()`) و گاهی ابتدا یک تابع را صدا می‌زنیم و رشته را جلوی نام تابع داخل پرانتز می‌گذاریم؟ در بعضی موارد، توابع به اشیا تعلق دارند، مانند `upper()` ، که فقط میتواند روی رشته‌های متنی اعمال شود. در این موارد، تابع را یک **method** می‌نامیم. در موارد دیگر، توابع به چیزی تعلق ندارند و می‌توان آنها را روی انواع مختلفی از اشیا استفاده کرد، درست مانند `len()`. به همین دلیل است که `"Ola"` را به عنوان یک پارامتر ورودی به تابع `len` می‌دهیم. + +### چکیده + +بسیار خب، صحبت راجع به رشته‌ها کافی است. تا اینجا شما موارد زیر را یاد گرفته‌اید: + +- **خط فرمان** - تایپ دستورات (کد) و دیدن نتایج در خط فرمان پایتون +- ** اعداد و رشته‌های متنی** - در پایتون اعداد برای محاسبات ریاضی و رشته‌ها به عنوان اشیا متنی استفاده می‌شوند +- **عملگرها** مانند `+` و `*`، برای ساخت یک مقدار جدید، چند مقدار را با هم ترکیب می‌کنند +- **توابع**- مانند `upper()` و `len()`، که بر روی اشیا، اعمالی را انجام می‌دهند. + +موارد گفته شده، مبانی تمام زبان‌های برنامه‌نویسی است که ممکن است بعدا بیاموزید. برای کارهای سخت‌تر آماده هستید؟ حتماً آماده‌اید! + +## خطاها + +بیایید چیز جدیدی را امتحان کنیم. می‌توانیم طول یک عدد را همانطور که طول نام خودمان را پیدا می‌کنیم، به دست آوریم؟ تایپ کنید`len(304023)` و `enter` را بزنید: + +{% filename %}{{ warning_icon }} خط فرمان{% endfilename %} + +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +اولین خطا را دریافت کردیم! به وسیله آیکن {{ warning_icon }} به شما اعلام می‌کنیم کدی که قرار است اجرا کنید، مطابق انتظار شما اجرا نخواهد شد. اشتباه کردن (حتی اشتباهات عمدی) بخش مهمی از یادگیری است! + +خطای دریافتی می‌گوید اشیا نوع "int" (اعداد طبیعی)، صفت "طول" ندارند. خب پس حالا چه کاری می‌توانیم بکنیم؟ می‌توانیم عددمان را به عنوان یک رشته متنی بنویسیم؟ رشته‌های متنی دارای طول هستند، درست است؟ + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> len(str(304023)) +6 +``` + +کار کرد! ما از تابع `str` داخل تابع `len` استفاده کردیم. `str()` هرچیزی را به رشته متنی تبدیل می کند. + +- تابع `str` ورودی‌اش را به **strings** تبدیل می‌کند +- تابع `int` ورودی‌اش را به **integers** تبدیل می‌کند + +> توجه: ما می‌توانیم اعداد را به متن تبدیل کنیم، اما همیشه نمی‌توان متن را به عدد تبدیل کرد - مثلا خروجی `int('hello')` چه چیزی می‌تواند باشد؟ + +## متغیرها + +یکی از مفاهیم مهم در برنامه‌نویسی، مفهوم متغیرها است. متغیر نامی است برای یک مقدار که بعدا بتوانید برای ارجاع به آن مقدار، از نام متغیر استفاده کنید. برنامه‌نویس‌ها از این متغیرها برای ذخیره داده، و بالا بردن خوانایی کد استفاده می‌کنند تا مجبور نباشند همه‌چیز را در ذهن نگه‌دارند. + +بیایید یک متغیر جدید به نام `name` بسازیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> name = "sara" +``` + +تایپ می‌کنیم name مساوی sara. + +همانطور که توجه کردید، برنامه شما مانند دفعات قبل خروجی نداد. پس از کجا بدانیم متغیر واقعا وجود دارد؟ نام متغیر `name` را وارد کنید و `enter` بزنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> name +'sara' +``` + +بلههههه! اولین متغیر شما!‌ :) همواره می‌توانید چیزی را که متغیر به آن ارجاع می‌دهد، تغییر دهید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> name = "Mahsa" +>>> name +'Mahsa' +``` + +می‌توانید از آن در توابع نیز استفاده کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> len(name) +5 +``` + +عالی است، نه؟ متغیرها می‌توانند هرچیزی باشند- مثل اعداد! این یکی را امتحان کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +ولی اگر نام اشتباه را استفاده کنیم چه می‌شود؟ می‌توانید حدس بزنید چه اتفاقی می‌افتد؟ بیایید امتحان کنیم! + +{% filename %}{{ warning_icon }} خط-فرمان{% endfilename %} + +```python +>>> city = "Tehran" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +یک خطا! همانطور که می‌بینید، پایتون دارای انواع مختلفی از خطاها است و این یکی خطا **NameError** نام دارد. اگر سعی کنید از متغیری که هنوز تعریف نشده استفاده کنید، پایتون این خطا را به شما می‌دهد. اگر بعداً به این خطا برخورد کردید، کد خود را برای اشتباه تایپی در نام متغیرها چک کنید. + +کمی این موارد را امتحان کنید تا ببینید چه کارهایی می‌توانید با آن انجام دهید! + +## تابع print + +این را امتحان کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> name = 'Mahsa' +>>> name +'Mahsa' +>>> print(name) +Mahsa +``` + +زمانی که فقط `name` را تایپ می‌کنید، مفسر پایتون با *ارائه‌ای* از رشته متنی داخل متغیر 'name' پاسخ می‌دهد، که این پاسخ دنباله کاراکترهای M-a-h-s-a درون علامت نقل قول است. وقتی که `print(name)` را اجرا می‌کنید، پایتون محتوای متغیر را در صفحه نمایش نشان می‌دهد، البته بدون علامت‌های نقل قول که مرتب‌تر است. + +بعداً خواهیم دید که `print()` زمانی که می‌خواهیم از داخل توابع چیزی را نمایش دهیم، یا زمانی که می‌خواهیم چندین خط از متن را نمایش دهیم، نیز مفید است. + +## لیست‌ها + +پایتون علاوه بر رشته ها و اعداد، انواع مختلفی از اشیا را دارد. و الان نوعی از اشیا را معرفی می‌کنیم که **list** نام دارند. لیست‌ها دقیقا همان چیزی هستند که فکرش را می‌کنید: یک نوع شی که خودش لیستی از اشیای دیگر است. :) + +حالا یک لیست بسازید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> [] +[] +``` + +بله، این لیست خالی است. آنقدر مفید نیست، درست است؟ بیایید یک لیست از اعداد بخت آزمایی بسازیم. ما نمی‌خواهیم یک عدد تکراری را انتخاب کنیم، پس اعداد بخت آزمایی را داخل یک متغیر می‌گذاریم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +بسیار خب، ما یک لیست داریم! چه کاری می‌توانیم با آن انجام دهیم؟ بیایید ببینیم چه تعداد عدد بخت آزمایی درون لیست داریم. هیچ ایده‌ای درمورد این که از چه تابعی باید استفاده کنیم، دارید؟ از قبل این را می‌دانید! + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> len(lottery) +6 +``` + +بله! تابع `len()` می‌تواند تعداد اشیای درون لیست را بدهد. بسیار مفید، درست است؟ حالا بیایید لیستمان را مرتب کنیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> lottery.sort() +``` + +این یکی هیچ خروجی نداد، بلکه فقط ترتیب قرارگرفتن اعداد در لیست را تغییر داد. بیایید دوباره لیست را چاپ کنیم و ببینیم چه اتفاقی افتاده: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +همانطور که می‌بینید، اعداد درون لیست از کمترین مقدار به بیشترین مقدار مرتب شده‌اند. تبریک! + +شاید بخواهیم ترتیب اعداد را برعکس کنیم. بیایید انجامش دهیم! + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +اگر می‌خواهید چیزی به لیست خود اضافه کنید، می‌توانید این دستور را تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +اگر می‌خواهید فقط عدد اول را نمایش دهید، می‌توانید این کار با استفاده از **indexes** انجام دهید. ایندکس شماره‌ای است که نشان دهنده محل قرار گرفتن یک آیتم در لیست است. برنامه‌نویس‌ها ترجیح می‌دهند شمردن را از 0 شروع کنند. پس شماره اولین شی در لیست 0 است، بعدی 1 است و الی آخر. دستور زیر را امتحان کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` + +همانطور که می‌بینید، می‌توانید به اشیاء مختلف موجود در لیست به کمک نام لیست و ایندکس آن شیء که درون یک براکت آمده باشد، دسترسی پیدا کنید. + +برای حذف چیزی از داخل لیست، باید همانطور که در بالا یاد گرفتیم، از **ایندکس** و متد `pop()` استفاده کنید. بیایید یک مثال را امتحان کنیم و چیزی را که قبلا یاد گرفتیم، بهبود دهیم؛ ما اولین عدد لیست را حذف خواهیم کرد. + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +مانند یک افسون عمل کرد! + +برای تفریح بیشتر، باقی ایندکس ها را نیز امتحان کنید:6 ،7، 1000، -1، -6، یا -1000. ببینید می‌توانید نتیجه را پیش از اجرای دستور، پیش بینی کنید؟ نتایج برای شما معنایی دارند؟ + +می توانید لیستی از متدهای مربوط به لیست‌ها را در این بخش از مستندات پایتون پیدا کنید: https://docs.python.org/3/tutorial/datastructures.html + +## دیکشنری‌ها + +> برای خوانندگان داخل خانه: این قسمت در ویدئوهای بخش [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c) پوشش داده شده است. + +دیکشنری شبیه به لیست است، ولی برای دسترسی به مقادیر باید از کلیدها به جای ایندکس‌های عددی استفاده کنید. یک کلید می‌تواند رشته متنی و یا عدد باشد. دستور زبان تعریف یک دیکشنری خالی این است: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> {} +{} +``` + +خروجی نشان می‌دهد که یک دیکشنری خالی ساخته‌اید. هورررااا! + +حالا سعی کنید که دستور زیر را بنویسید (سعی کنید اطلاعات خود را نیز جایگزین کنید): + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> participant = {'name': 'Mahsa', 'country': 'Iran', 'favorite_numbers': [7, 42, 92]} +``` + +با این دستور، یک متغیر به نام `participant` شامل سه جفت کلید-مقدار ساخته‌اید: + +- کلید `name` به مقدار `Mahsa` (یک شی `string` ) اشاره می‌کند +- کلید `country` به `'Iran'` (یک `string` دیگر) اشاره می‌کند +- و کلید `favorite_numbers` به `[7, 42, 92]` اشاره می‌کند (یک `لیست` با سه عدد داخل آن). + +می‌توانید محتوای هر کلید را طبق دستور زیر به تنهایی چک کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> print(participant['name']) +Mahsa +``` + +ببینید، دیکشنری مشابه یک لیست است. ولی نیازی نیست که ایندکس ها را بخاطر بیاورید - فقط کافی است نام کلید را بدانید. + +اگر مقدار کلیدی را که وجود ندارد از پایتون درخواست کنیم چه اتفاقی می‌افتد؟ می‌توانید حدس بزنید؟ بیایید امتحان کنیم و ببینیم! + +{% filename %}{{ warning_icon }} خط فرمان{% endfilename %} + +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` + +ببینید، یک خطای دیگر! این یکی **KeyError** است. پایتون به شما کمک می‌کند و می‌گوید که کلید `'age'` در دیکشنری وجود ندارد. + +چه زمانی از لیست و چه زمانی از دیکشنری باید استفاده کرد؟ نکته خوبی است. قبل از دیدن خط بعد به پاسخ فکر کنید. + +- یک دنباله ترتیبی از آیتم ها نیاز دارید؟ لیست را انتخاب کنید. +- آیا نیاز است کلیدها و مقادیر را به همدیگر ارتباط دهید، که بعدا بتوانید به صورت کارآمد مقادیر را بوسیله کلیدها جستجو کنید؟ از یک دیکشنری استفاده کنید. + +دیکشنری‌ها، مانند لیست‌ها *تغییر پذیر* هستند، به معنای آن که می‌توان آن‌ها را پس از ساخت، تغییر داد. می‌توانید پس از ساختن دیکشنری، جفت کلید-مقدار جدید به آن اضافه کنید، مانند زیر: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +استفاده از متد `len()` روی دیکشنری، مانند لیست‌ها، تعداد جفت‌های کلید-مقدار را برمی‌گرداند. دستور زیر را تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> len(participant) +4 +``` + +امیدواریم تا اینجا همه چیز برایتان روشن باشد. :) آماده تفریح بیشتر با دیکشنری‌ها هستید؟ ادامه آموزش را بخوانید تا با چیزهای شگفت انگیز روبرو شوید. + +می‌توانید از متد `pop()` برای حذف یک آیتم از دیکشنری استفاده کنید. برای مثال، اگر می‌خواهید مدخل مربوط به کلید `'favorite_numbers'` را حذف کنید، دستور زیر را تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> participant +{'country': 'Iran', 'favorite_language': 'Python', 'name': 'Mahsa'} +``` + +همانطور که در خروجی مشاهده می‌کنید، کلید مقدار متناظر با 'favorite_numbers' حذف شده است. + +به همین شکل، می‌توانید مقدار مربوط به یک کلید موجود در دیکشنری را تغییر دهید. این را تایپ کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Mahsa'} +``` + +همانطور که می‌توانید ببینید مقدار کلید `'country'` از `'Iran'` به `'Germany'` تغییر پیدا کرده‌است. :) هیجان انگیز نیست؟ هورا! همین الان یک مورد شگفت انگیز دیگر یاد گرفتید. + +### چکیده + +بسیار عالی! الان چیزهای زیادی راجع به برنامه‌نویسی می‌دانید. در همین قسمت آخر شما موارد زیر را آموختید: + +- **خطاها** - اگر پایتون دستوری را متوجه نشود و خطایی را نشان دهد، حالا شما می‌دانید چطور آن خطا را بخوانید و درک کنید +- **متغیرها** - نام‌هایی برای اشیا هستند که شما را قادر می‌سازد راحت تر کد بزنید و کد شما را خواناتر می‌کند +- **لیست‌ها** - لیستی از اشیا که در یک ترتیب خاص ذخیره شده‌اند +- **دیکشنری‌ها** - اشیایی که به عنوان جفت‌های کلید-مقدار ذخیره شده‌اند + +برای بخش بعدی هیجان زده‌اید؟ :) + +## مقایسه اشیا + +> برای خوانندگان داخل خانه: این قسمت در ویدئو های بخش [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) پوشش داده شده است. + +بخش بزرگی از برنامه‌نویسی شامل مقایسه اشیا است. مقایسه چه چیزهایی از همه راحت‌تر است؟ اعداد! بیایید نحوه کارکرد آن را ببینیم: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +ما به پایتون تعدادی عدد برای مقایسه کردن داده‌ایم. همانطور که می‌بینید، پایتون نه تنها می‌تواند اعداد را مقایسه کند بلکه می‌تواند عبارت‌های ریاضی مانند `2 * 2` و متدهایی همچون `len([4, 5])` که نتیجه `2` را می‌دهد نیز با هم مقایسه کند. جالب است، نه؟ + +آیا به این فکر کرده‌اید که چرا دو علامت مساوی `==` کنار هم برای چک کردن تساوی اعداد گذاشته‌ایم؟ ما از یک علامت مساوی `=` برای انتساب مقادیر به متغیرها استفاده می‌کنیم. اگر می‌خواهید مساوی بودن دو شی با همدیگر را چک کنید، همیشه و **همیشه** باید از دو علامت مساوی `==` استفاده کنید. همچنین می‌توانیم مساوی نبودن اشیا را تعیین کنیم. برای این منظور، از علامت `=!`، همانطور که در مثال بالا نشان داده شده است، استفاده می‌کنیم. + +دو تمرین دیگر با پایتون انجام بدهید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +ما `>` و `<` را دیدیم، ولی `>=` و `<=` چه معنایی دارد؟ آنها را به این صورت بخوانید: + +- x `>` y یعنی‌: x بزرگتر از y است +- x `<` y یعنی: x کوچکتر از y است +- x `<=` y یعنی: x کوچکتر یا مساوی y است +- x `>=` y یعنی: x بزرگتر یا مساوی y است + +بسیارعالی! می‌خواهید بیشتر با آن کار کنید؟ این را امتحان کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> 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 ارزیابی شود + +آیا عبارت " مقایسه سیب با پرتقال" را شنیده‌اید؟ بیایید نسخه پایتونی آن را امتحان کنیم: + +{% filename %}{{ warning_icon }} خط فرمان {% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and 'str' +``` + +همانطور که در عبارت بالا می‌بینید، پایتون قادر نیست یک رشته (`str`) و یک عدد (`int`) را با هم مقایسه کند. درعوض، یک **TypeError** نشان می‌دهد و به ما می‌گوید که دو نوع نمی‌توانند با یکدیگر مقایسه شوند. + +## Boolean + +در حقیقت شما با نوع جدیدی از اشیا در پایتون آشنا شدید. به نام **Boolean** بولیَن. + +فقط دو نوع شی بولین وجود دارد: + +- True - درست +- False - نادرست + +برای اینکه پایتون این نوع را بشناسد، باید همیشه آن را به صورت 'True' بنویسید (حرف اول بزرگ، و باقی حروف کوچک). **true, TRUE, و tRUE را نخواهد شناخت - فقط Trueدرست است.** ( برای False هم همینطور.) + +بولین ها می توانند به صورت متغیر باشند، اینجا را ببینید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +می‌توانید به این صورت نیز انجامش دهید: + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +با اجرای دستورات زیر، با بولین ها تفریح و تمرین کنید: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 =! 2` + +تبریک! بولین‌ها یکی از جالب ترین ویژگی‌های برنامه‌نویسی هستند، و شما همین الان یاد گرفتید چطور از آن‌ها استفاده کنید! + +# ذخیره کنید! + +> برای خوانندگان داخل خانه: این قسمت در ویدئو های بخش [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk) پوشش داده شده است. + +تا اینجا ما تمام کدهای پایتون خود را در مفسر خط فرمان نوشته‌ایم، که ما را محدود به ورود یک خط از کد در یک زمان می‌کرد. برنامه‌های نرمال در فایل ذخیره می‌شوند و به وسیله **مفسر** یا **کامپایلر** زبان برنامه‌نویسی اجرا می‌شوند. تا اینجا ما برنامه‌هایمان به صورت - هربار، یک خط - در **مفسر** پایتون اجرا کردیم. برای تمرین‌های بعدی به بیش از یک خط کد نیاز خواهیم داشت، پس ما نیاز داریم تا سریعاً: + +- از مفسر پایتون خارج شویم +- ویرایشگر متنی دلخواه خود را نصب کنیم +- چندخط کد در فایل جدید پایتون ذخیره کنیم +- آن را اجرا کنیم! + +برای خروج از مفسر پایتونی که در حال استفاده از آن هستیم، تابع `exit()` را تایپ کنید + +{% filename %}خط فرمان{% endfilename %} + +```python +>>> exit() +``` + +این عمل شما را به خط فرمان بازمی‌گرداند. + +پیش از این، ما یک ویرایشگر متنی از بخش [ویرایشگر متن](../code_editor/README.md) انتخاب کردیم. حالا باید ویرایشگر را باز کنیم و چند خط کد در یک فایل جدید بنویسیم (یا اگر از یک کروم بوک استفاده می کنید، یک فایل جدید روی cloud IDE بسازید و فایل را باز کنید): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +به وضوح، حالا شما یک توسعه دهنده پایتون کاربلد هستید، پس کمی از کدهایی که امروز یاد گرفتید را بنویسید. + +حالا باید فایل را ذخیره کنیم و یک نام توصیفی به آن بدهیم. بیایید فایل را **python_intro.py** نامگذاری کنیم و آن را روی صفحه دسکتاپ ذخیره کنیم. می‌توانیم به فایل هر نامی که می‌خواهیم بدهیم، ولی پایان یافتن فایل با **.py** مهم است. پسوند **.py** به سیستم عامل می‌گوید که این یک **فایل اجرایی پایتون** است و پایتون می تواند آن را اجرا کند. + +> **توجه** شما باید به یکی از جالب‌ترین ویژگی‌های ویرایشگر کد دقت کنید: رنگ‌ها! در کنسول پایتون، همه چیز به یک رنگ بود، حالا شما می‌توانید ببینید که تابع `print` رنگ متفاوتی با رشته متنی دارد. به این ویژگی "برجسته سازی دستوری " می‌گویند، که ویژگی بسیار مفیدی برای کد زدن است. رنگ چیزها شما را راهنمایی می‌کند، مانند رشته متنی بسته نشده یا غلط دیکته ای در کلمات کلیدی (مانند `def` در یک تابع که در ادامه خواهیم دید). این یکی از دلایلی است که از ویرایشگر کد استفاده می‌کنیم. :) + +وقتی فایل را ذخیره کردیم وقت آن است که آن را اجرا کنیم! ار مهارت‌هایی که در بخش خط فرمان گفتیم استفاده کنید، از ترمینال برای **تغییر دایرکتوری** به دسکتاپ استفاده کنید. + + + +بر روی Mac، فرمان‌ها شبیه به این خواهد بود: + +{% filename %}خط فرمان{% endfilename %} + + $ cd ~/Desktop + + + + + + +بر روی لینوکس شبیه به این است: + +{% filename %}خط فرمان{% endfilename %} + + $ cd ~/Desktop + + +(به یاد داشته باشید که ممکن است کلمه "Desktop" به زبان منتخب شما ترجمه شده باشد.) + + + + + +در خط فرمان ویندوز، شبیه به این است: + +{% filename %}خط فرمان{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +بر روی پاورشل ویندوز، شبیه به این است: + +{% filename %}خط فرمان{% endfilename %} + + > cd $Home\Desktop + + + + +اگر گیر کردید تقاضای راهنمایی کنید. مربی‌ها برای همین کار در کنار شما هستند! + +حالا از پایتون استفاده کنید تا کدهای موجود در فایل را اجرا کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + Hello, Django girls! + + +نکته: در ویندوز 'pyhton3' یک دستور محسوب نمیشود. به جای آن از 'python' برای اجرای فایل استفاده کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +> python python_intro.py +``` + +بسیار خب! شما اولین برنامه پایتون خود را که در یک فایل ذخیره شده بود اجرا کردید. فوق العاده نیستید؟ + +حالا شما می‌توانید به سراغ یکی از ابزارهای ضروری برنامه نویسی بروید: + +## If … elif … else + +بسیاری از کدها تنها زمانی باید اجرا شوند که شروط داده شده درست باشند. به همین دلیل پایتون چیزی به نام دستور شرطی - **دستور if** دارد. + +کد خود را در فایل **python_intro.py** با این جایگزین کنید: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: +``` + +اگر ما این را ذخیره و اجرا کنیم، خطایی مانند زیر را مشاهده می‌کنیم: + +{% filename %}{{ warning_icon }} خط-فرمان{% endfilename %} + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +پایتون انتظار دارد که ما مشخص کنیم اگر شرط `3 > 2` درست باشد چه دستوری باید اجرا شود (یا به صورت صحیح‌تر شرط `True` باشد). بیایید کاری کنیم که در صورت درست بودن شرط، پایتون در خروجی بنویسد: “It works!”. کد را در فایل **python_intro.py** به این تغییر دهید: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: + print('It works!') +``` + +به تورفتگی خط بعدی کد به اندازه 4 اسپیس دقت کردید؟ به این تورفتگی ها نیاز داریم تا پایتون بداند در صورت درست بودن شرط کدام دستورات را اجرا کند. می توانید از یک اسپیس استفاده کنید، ولی تقریبا همه برنامه‌نویسان پایتون برای تمیزی و خوانایی کد از 4 اسپیس استفاده می کنند. همچنین می‌توانید ویرایشگر کد خود را طوری تنظیم کنید تا یک tab به عنوان 4 اسپیس محسوب شود. زمانی که انتخاب خود را تعیین کردید، آن را تغییر ندهید! اگر تورفتگی را با 4 اسپیس انجام می‌دهید، تمام تورفتگی های بعدی را با 4 اسپیس انجام دهید، درغیر این صورت به مشکل برمی‌خورید. + +فایل را ذخیره کنید و بار دیگر اجرا کنید: + +{% filename %}خط فرمان{% endfilename %} + +```python +$ python3 python_intro.py +It works! +``` + +توجه: یادتان باشد که در ویندوز 'python3' به عنوان یک دستور شناخته نمی‌شود. از الان به بعد 'python3' را با 'python' برای اجرای فایل ها جایگزین کنید. + +### چه می‌شود اگر یک شرط True نباشد؟ + +در مثال قبلی، کد تنها زمانی اجرا می‌شد که شرط‌ها درست بودند. ولی پایتون دستورات `elif` و `else` هم دارد: + +{% filename %}python_intro.py{% endfilename %} + +```python +if 5 > 2: + print('5 is indeed greater than 2') +else: + print('5 is not greater than 2') +``` + +وقتی آن را اجرا کنید، خروجی زیر را نمایش می‌دهد: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +اگر 2 عدد بزرگتری از 5 بود، دستور دوم اجرا می‌شد. بیایید نحوه کار `elif` را ببینیم: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +و اجرا کنید: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + Hey Sonja! + + +دیدید چه اتفاقی افتاد؟ `elif` شما را قادر میسازد تا شرط های بیشتری اضافه کنید تا اگر شروط قبلی درست نبودند، شروط جدید ارزیابی شوند. + +میتوانید هر تعداد `elif` که خواستید پس از `if` اولیه اضافه کنید، به عنوان مثال: + +{% 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! :(") +``` + +پایتون تمام شرط ها را به ترتیب ارزیابی می‌کند و چاپ می‌کند: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + Perfect, I can hear all the details + + +## کامنت‌ها + +کامنت‌ها خطوطی هستند که با `#` شروع می‌شوند. می‌توانید بعد از `#` هر توضیحاتی راجع به کد بنویسید و پایتون آن را نادیده می‌گیرد. کامنت‌ها می‌توانند کد شما را برای دیگران خواناتر کنند. + +بیایید ببینیم چطور دیده می‌شود: + +{% 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!") +``` + +نیازی نیست برای هر خط کد کامنت بنویسید، ولی برای توضیح اینکه چرا کد شما کاری را انجام می‌دهد یا برای داشتن یک خلاصه، زمانی که کد کار پیچیده‌ای را انجام می‌دهد، مفید اند. + +### چکیده + +در تمرین های اخیر شما موارد زیر را یاد گرفتید: + +- **مقایسه اشیا** - در پایتون می‌توانید اشیا را به وسیله `>` و `>=` و `==` و `<=` و `<` و عملگرهای `and` و `or` مقایسه کنید +- **بولین‌ها** - نوعی از اشیا که می‌تواند فقط دو مقدار معتبر بگیرد: `True` یا `False` +- ** ذخیره فایل‌ها** - ذخیره کردن کدها در فایل تا بتوانید برنامه‌های بزرگتری را اجرا کنید. +- **if … elif … else** - دستوراتی که شما را قادر می‌سازد کدها را زمانی اجرا کنید که شروط مشخصی درست باشند. +- **کامنت‌ها** - خطوطی که پایتون آن‌ها را به عنوان کد اجرا نمی‌کند، و به شما اجازه می‌دهد تا کد خود را مستند سازی کنید + +زمان آخرین بخش از این فصل رسیده است! + +## تابع خودتان را بنویسید! + +> برای خوانندگان داخل خانه: این قسمت در ویدئو های بخش [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) پوشش داده شده است. + +توابعی مانند `len()` را که می‌توانید در پایتون اجرا کنید، به خاطر دارید؟ بسیار خوب - شما الان یاد می‌گیرید که چطور تابع خود را بنویسید! + +یک تابع دنباله‌ای از دستورات است که پایتون باید اجرا کند. همه توابع در پایتون با کلمه کلیدی `def` شروع می شوند، نام می‌گیرند و می‌توانند پارامترهای ورودی داشته باشند. بیایید امتحانش کنیم. کد داخل فایل **python_intro.py** را با این جایگزین کنید: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +خب، اولین تابع ما آماده است! + +شاید فکر می‌کنید که چرا نام تابع را در انتهای فایل نوشته‌ایم. وقتی که ما عبارت `def hi():` و خطوط تو رفته زیر آن را می‌نویسیم، دستورالعمل‌هایی را که باید توسط تابع `hi()` اجرا شوند مشخص می‌کنیم. پایتون این دستورالعمل‌ها را می‌خواند و به یاد می‌آورد اما آن را اجرا نمی‌کند. برای آنکه به پایتون بگوییم که این تابع را اجرا کند، باید تابع را فراخوانی کنیم یا آن را با عبارت `hi()` صدا بزنیم. پایتون فایل را می‌خواند و آن را از بالا به پایین اجرا می‌کند، بنابراین ما باید قبل از صدا زدن آن، عملکرد تابع را در فایل تعریف کرده باشیم. + +بیایید این را اجرا کنیم و ببینیم چه اتفاقی می‌افتد: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +توجه: اگر درست کار نکرد، نترسید! خروجی به شما کمک می کند دلیل آن را بفهمید: + +- اگر یک خطای `NameError` دریافت کردید، احتمالا چیزی را اشتباه تایپ کرده‌اید، پس چک کنید که از نام یکسانی موقع ساختن تابع با `def hi():` و صدا کردن آن با `hi()` استفاده کرده‌باشید. +- اگر یک خطای `IndentationError` دریافت کردید، چک کنید که هر دو دستور `print` تورفتگی یکسانی دارند: پایتون می‌خواهد که تمام کدهای داخل تابع به درستی قرار بگیرند و هم راستا باشند. +- اگر اصلا چیزی چاپ نشده، چک کنید که آخرین `hi()` تورفته *نباشد* - اگر تورفتگی داشته‌باشد، بخشی از کد تابع می‌شود و هرگز اجرا نمی‌شود. + +بیایید اولین تابع خود را با پارامتر ورودی بسازیم. ما مثال قبلی را تغییر می‌دهیم - تابعی که به فرد اجرا کننده آن سلام می‌کند - با نام خود فرد: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): +``` + +همانطور که می‌بینید، ما الان به تابع یک پارامتر به نام `name` دادیم: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +hi() +``` + +به خاطر داشته باشید: تابع `print` با 4 اسپیس داخل دستور `if` تورفتگی دارد. بخاطر آنکه تابع زمانی اجرا می‌شود که شرط درست باشد. بیایید نحوه کار آن را ببینیم: + +{% filename %}{{ warning_icon }} خط-فرمان{% 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' + + +آخ، خطا. خوشبختانه، پایتون یک پیام خطای مفید به ما می‌دهد. به ما می‌گوید که تابع `hi()` (همانی که تعریف کردیم) یک پارامتر ورودی دارد (به نام `name`) و ما فراموش کردیم زمان صدا کردن تابع آن را وارد کنیم. بیایید آن را در انتهای فایل درست کنیم: + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Ola") +``` + +و دوباره اجرا کنیم: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + Hi Ola! + + +و اگر نام را تغییر دهیم چه می‌شود؟ + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Sonja") +``` + +و اجرا کنیم: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + Hi Sonja! + + +فکر میکنید اگر نام دیگری را بنویسید چه اتفاقی می‌افتد؟(بغیر از Ola یا Sonja). امتحان کنید و ببینید که درست فکر می کردید یا نه. باید این را نمایش دهد: + +{% filename %}خط فرمان{% endfilename %} + + Hi anonymous! + + +عالی است.نه؟ با این روش، نیاز نیست برای هر تغییر نامی که تابع به آن سلام میکند، کار تکراری انجام دهید. ما دقیقا توابع را برای همین نیاز داریم - شما نمی‌خواهید تا هر دفعه کد خود را تکرار کنید! + +بیایید کار هوشمندانه‌تری انجام دهیم - بیشتر از 2 اسم داریم، و نوشتن یک شرط برای هر کدام سخت است. درست است؟ محتوای فایل خود را با فایل زیر جایگذاری کنید: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +حالا بیایید تا کد را صدا بزنیم: + +{% filename %}خط فرمان{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + + +تبریک! شما همین الان نحوه نوشتن توابع را یاد گرفتید! :) + +## حلقه‌های تکرار + +> برای خوانندگان داخل خانه: این قسمت در ویدئو های بخش [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) پوشش داده شده است. + +این آخرین بخش است. سریع تمام شد درست است؟ :) + +برنامه‌نویس‌ها دوست ندارند کار تکراری انجام دهند. برنامه‌نویسی برای اتوماتیک کردن کارها است، پس ما نمی‌خواهیم به طور غیر اتوماتیک به هر فرد سلام کنیم، درست است؟ این همان جایی است که حلقه‌های تکرار - Loop - به کار می‌آیند. + +هنوز لیست‌ها را به خاطر دارید؟ بیایید یک لیست از دختران بسازیم: + +{% filename %}python_intro.py{% endfilename %} + +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + +ما می‌خواهیم به همه آنها با ذکر نامشان سلام کنیم. برای این کار تابع `hi` را داریم، بیایید در یک حلقه از آن استفاده کنیم: + +{% filename %}python_intro.py{% endfilename %} + +```python +for name in girls: +``` + +عبارت `for` کمی شبیه به عبارت `if` رفتار می‌کند؛ کد زیر هر دو باید به اندازه 4 اسپیس تو رفتگی داشته باشد. + +اینجا کد کاملی را که باید در فایل باشد، داریم: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +و وقتی آن را اجرا کنیم: + +{% filename %}خط فرمان{% 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 + + +همانطور که می‌بینید، هر چیزی که درون یک عبارت `for` با تورفتگی قرار دهید، برای هر المان لیست `girls` تکرار می‌شود. + +همچنین می‌توانید از `for` با استفاده تابع `range` روی اعداد نیز استفاده کنید: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +که چاپ می کند: + +{% filename %}خط فرمان{% endfilename %} + + 1 + 2 + 3 + 4 + 5 + + +`range` تابعی است که لیستی از اعداد متوالی را می‌سازد (ابتدا و انتهای بازه توسط شما به عنوان پارامتر به تابع داده می شود). + +توجه کنید که کران بالای بازه -دومین پارامتر- در لیست ساخته‌شده توسط پایتون نمی‌آید (به این معناست که `range(1, 6)` از 1 تا 5 می‌شمارد، اما شامل 6 نمی‌شود). به دلیل این که "range" نیمه‌باز است، و منظور این است که شامل عدد ابتدای بازه می‌شود ولی عدد انتهایی را شامل نمی‌شود. + +## چکیده + +همین بود. **شما فوق‌العاده هستید!** این بخش دارای ریزه کاری هایی بود و شما باید به خودتان افتخار کنید. ما هم قطعاً به شما افتخار می‌کنیم که تا اینجا پیش آمده اید! + +برای دیدن آموزش رسمی و کامل پایتون آدرس https://docs.python.org/3/tutorial/ را ببینید. این آموزش به شما دید کامل‌تر و درست‌تری نسبت به این زبان می‌دهد. موفق باشید! :) + +شاید بخواهید قبل از رفتن به مرحله بعد، کارهای دیگری بکنید، کمی کش قوس بیایید، قدم بزنید و به چشم های خود استراحتی بدهید. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/fa-IR/template_extending/README.md b/fa-IR/template_extending/README.md new file mode 100644 index 00000000000..a2aa76589ec --- /dev/null +++ b/fa-IR/template_extending/README.md @@ -0,0 +1,151 @@ +# توسعه template + +چیز دیگری که جنگو برای شما دارد **توسعه template** است. معنای آن چیست؟ به این معنی است که شما می‌توانید بخش‌هایی از یک کد HTML را در چندین صفحه مختلف از وب سایت خود استفاده کنید. + +زمانی که قصد دارید از اطلاعات یا ترکیب بندی خاصی چندین بار استفاده کنید، template ها به کمک شما خواهند آمد. نیازی نیست که یک کار تکراری را برای همه فایل ها انجام دهید. و اگر قصد داشتید چیزی را تغییر دهید، لازم نیست آن تغییر را در تک تک template ها اعمال کنید. فقط یکبار کافی است! + +## ساخت یک template پایه + +یک template پایه، اساسی ترین template است که شما آن را در هر صفحه وب سایت خود توسعه می‌دهید. + +اجازه دهید تا یک فایل `base.html` در مسیر `blog/templates/blog/` بسازیم: + + blog + └───templates + └───blog + base.html + post_list.html + + +سپس فایل را در ویرایشگر متنی باز کنید و همه چیز را از فایل `post_list.html` داخل فایل `base.html` کپی کنید، مانند زیر: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +سپس در فایل `base.html`, همه محتویات تگ `` (همه چیز بین `` و ``) را با کد زیر عوض کنید: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %} ممکن است توجه کرده باشید که این عمل هر چیزی بین `{% for post in posts %}` و `{% endfor %}` را با کد زیر عوض کرده است: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +ولی چرا؟ شما همین الان یک `block` ساختید! شما از تمپلیت تگ `{% block %}` برای ساخت یک ناحیه استفاده کردید، که کد HTML در آن قرار می‌گیرد. زمانی که تمپلیت `base.html` را در فایل تمپلیت دیگری گسترش می‌دهیم، کدهای HTML مذکور را داخل تگ block می‌نویسیم. ما نحوه انجام کار را همین الان به شما نشان خواهیم داد. + +فایل `base.html` را ذخیره کنید و فایل `blog/templates/blog/post_list.html` را دوباره در ویرایشگر متنی باز کنید. {% raw %} شما قرار است همه چیز را از بالای `{% for post in posts %}` و زیر `{% endfor %}` حذف کنید. زمانی که کار گفته شده را انجام دادید، فایل به این شکل خواهد بود:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +ما می‌خواهیم از این بخش template برای تمام بلاک‌های محتوا استفاده کنیم. زمان اضافه کردن تگ‌های block به این فایل رسیده‌است! + +{% raw %} شما می‌خواهید که تگ block با تگ‌های فایل `base.html` هماهنگ باشد. هم چنین می‌خواهید تا این تگ تمام کدهای متعلق به بلاک محتوا را شامل شود. برای انجام این کار، همه چیز را بین `{% block content %}` و `{% endblock %}` قرار دهید. به این صورت:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +تنها یک کار باقی مانده. ما باید این دو template را به یکدیگر متصل کنیم. هدفمان از گسترش template همین است! با اضافه کردن تگ extends در ابتدای فایل، این کار را انجام می‌دهیم. مانند زیر: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +همین است! فایل را ذخیره کنید، و چک کنید که آیا وب‌سایت شما هنوز به درستی کار می‌کند. :) + +> اگر خطای`TemplateDoesNotExist` را دریافت کردید، به معنای آن است که فایل `blog/base.html` وجود ندارد و دستور `runserver` در کنسول خط فرمان در حال اجرا است. سعی کنید دستور را متوقف کنید (با زدن Ctrl+C - کلید Control و کلید C به صورت همزمان) و وب سرور را دوباره با دستور `python manage.py runserver` راه اندازی کنید. \ No newline at end of file diff --git a/fa-IR/whats_next/README.md b/fa-IR/whats_next/README.md new file mode 100644 index 00000000000..9a14d147f2a --- /dev/null +++ b/fa-IR/whats_next/README.md @@ -0,0 +1,43 @@ +# گام بعدی چیست؟ + +تبریک به شما! **شما فوق العاده هستید**. به شما افتخار می‌کنیم! <3 + +### حالا چه باید کرد؟ + +یک نفس راحت بکش. همین حالا هم یک کار واقعاٌ بزرگ انجام دادی. + +بعد از این مطمئن شو که جنگو گرلز را در [فیسبوک](http://facebook.com/djangogirls) یا [توییتر](https://twitter.com/djangogirls) دنبال میکنی تا در جریان تازه‌ترین‌ها باشی. + +### آیا می‌توانید منابع دیگری معرفی کنید؟ + +بله! حجم *بسیار زیادی* منابع آنلاین برای یادگرفتن هر نوع مهارت برنامه نویسی وجود دارد - این می‌تواند به راحتی باعث سردرگمی بشود اما ما از شما حمایت می‌کنیم. هرچیزی که باعث شد که شما به جنگو گرلز بیایید و یا هرچیزی که در طول دوره آموزش برایتان جالب بوده، ما منابعی کاملاً رایگان (یا با بخش‌هایی رایگان) برای آن‌ها معرفی می‌کنیم که شما می‌توانید به هر شکلی که بخواهید از آنها استفاده کنید. + +#### جنگو + +- کتاب دیگر ما، [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [دوره آموزشی رسمی جنگو](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [شروع کردن جنگو با درس‌های ویدئویی](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django)، برخی ویدئوها به رایگان قابل استفاده است و می‌توانید بعد از گذراندن این دوره‌ها مدرک Coursera بگیرید + +#### HTML, CSS and JavaScript + +- [دوره توسعه وبسایت Codecademy](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### پایتون + +- [دوره پایتون Codecademy](https://www.codecademy.com/learn/learn-python) +- [دوره پایتون گوگل](https://developers.google.com/edu/python/) +- [کتاب Learn Python The Hard Way](http://learnpythonthehardway.org/book/) - تمرین‌های ابتدایی رایگان است +- [دوره آموزشی New Coder](http://newcoder.io/tutorials/) - مجموعه‌ای از تمرین ‌های کاربردی است که نشان می‌دهد چطور از پایتون می‌توان استفاده کرد +- [edX](https://www.edx.org/course?search_query=python) - بسیاری از دوره‌ها را می‌توانید رایگان استفاده کنید، ولی اگر مدرک یا تأییدیه بخواهید باید هزینه بپردازید +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) - برخی از دوره‌ها رایگان هستند و با گذراندن آنها می‌توانید مدرک دوره را بگیرید +- [Python for Everybody](https://www.py4e.com/) - یک دوره آزاد و رایگان بر اساس Coursera Python for Everybody + +#### کار کردن با داده‌ها + +- [دوره علم داده Codecademy](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) - بسیاری از دوره‌ها را رایگان می‌توانید شرکت کنید ولی اگر مدرک یا تأییدیه می‌خواهید باید هزینه بپردازید +- [Dataquest](https://www.dataquest.io/) - سی "مأموریت" اول رایگان هستند + +نمی‌توانیم صبر کنیم تا ببینیم چه چیزی درست می‌کنید! \ No newline at end of file diff --git a/fa/GLOSSARY.md b/fa/GLOSSARY.md new file mode 100644 index 00000000000..c3ba34b6028 --- /dev/null +++ b/fa/GLOSSARY.md @@ -0,0 +1,3 @@ +# ویرایشگر کد ویرایشگر کد یک برنامه است که به شما اجازه میدهد کدهایتان را ذخیره کنید بنابراین شما میتوانید به آنها رجوع کنید. شما میتوانید در فصل editor chapter یاد بگیرید که یکی از آنها را چطور دانلود کنید. + +Code editor is an application that allows you to save your code so you will be able to get back to it later. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/fa/README.md b/fa/README.md new file mode 100644 index 00000000000..431f4c64f49 --- /dev/null +++ b/fa/README.md @@ -0,0 +1,51 @@ +# جنگو برای دختران + +[![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/ + +## Welcome + +Welcome to the Django Girls Tutorial! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) + +## معرفی + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? آیا شده به ساختن یک وبسایت فکر کنید ولی انگیزه کافی را برای شروع اش نداشته باشید؟ آیا شده به ساختن یک وبسایت فکر کنید ولی انگیزه کافی را برای شروع آن نداشته باشید؟ + +ما خبرهای خوبی برای شما داریم. برنامه نویسی آن قدر که به نظر می‌رسد سخت نیست و می‌خواهیم نشان دهیم که حتی میتواند جالب هم باشد. + +This tutorial will not magically turn you into a programmer. اگر بخواهید برنامه نویس خوبی شوید، باید ماهها و یا حتی سالها برایش وقت بگذارید. ولی ما می‌خواهیم نشان دهیم که برنامه نویسی آنقدر که به نظر می‌رسد پیچیده نیست. سعی ما این است که قدم به قدم و جز به جز جلو برویم، تا زیاد گیج نشوید. + +امیدواریم که بتوانیم کاری کنیم که شما در حد امکان از فناوری خوشتان بیاید. + +## در این آموزش چه چیزی یاد خواهید گرفت؟ + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +این (کم و بیش) شبیه این خواهد شد: + +![عدد 0.1](images/application.png) + +> 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). ما بوسیله پرسش از مربی هایمان٫ شرکت کننده گان قبلیمان و ... به ما کمک می‌کنند در توسعه این آموزش! نگران هیچ چیز نباشید سوالات خود را بپرسید! + +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. + +## مشارکت در توسعه + +این آموزش نگهداری می‌شود توسط [DjangoGirls](https://djangogirls.org/). در صورتی که مشکلی در این آموزش می‌بینید لطفا در بروزرسانی و حل آن مشکل به ما کمک کنید. [راهنمای نحوه توسعه](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## Would you like to help us translate the tutorial into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/fa/SUMMARY.md b/fa/SUMMARY.md new file mode 100644 index 00000000000..f891169f2fc --- /dev/null +++ b/fa/SUMMARY.md @@ -0,0 +1,27 @@ +# سرفصل ها + +* [معرفی](README.md) +* [نصب و راه‌اندازی](installation/README.md) +* [نصب و راه اندازی (chromebook)](chromebook_setup/README.md) +* [اینترنت چگونه کار می‌کند](how_the_internet_works/README.md) +* [آشنایی با خط فرمان](intro_to_command_line/README.md) +* [نصب و راه اندازی پایتون](python_installation/README.md) +* [ویرایشگر کد](code_editor/README.md) +* [آشنایی با پایتون](python_introduction/README.md) +* [جنگو چیست؟](django/README.md) +* [نصب و راه اندازی جنگو](django_installation/README.md) +* [Your first Django project!](django_start_project/README.md) +* [مدل در جنگو](django_models/README.md) +* [پنل مدیریت در جنگو](django_admin/README.md) +* [فاز دیپلوی!](deploy/README.md) +* [آدرس دهی در جنگو](django_urls/README.md) +* [Django views – time to create!](django_views/README.md) +* [آشنایی با HTML](html/README.md) +* [ORM در جنگو](django_orm/README.md) +* [داده های پویا در templates](dynamic_data_in_templates/README.md) +* [templates در جنگو](django_templates/README.md) +* [CSS – make it pretty](css/README.md) +* [توسعه template](template_extending/README.md) +* [توسعه application شما](extend_your_application/README.md) +* [فرم در جنگو](django_forms/README.md) +* [گام بعدی چیست؟](whats_next/README.md) \ No newline at end of file diff --git a/fa/chromebook_setup/README.md b/fa/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/fa/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/fa/chromebook_setup/instructions.md b/fa/chromebook_setup/instructions.md new file mode 100644 index 00000000000..809281456d3 --- /dev/null +++ b/fa/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +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 the 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 your 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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/fa/code_editor/README.md b/fa/code_editor/README.md new file mode 100644 index 00000000000..2e1cfbaba69 --- /dev/null +++ b/fa/code_editor/README.md @@ -0,0 +1,11 @@ +# ویرایشگر کد + +> برای خوانندگان در خانه: این فصل در ویدئو [نصب پایتون و کد ویرایشگر](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) توضیح داده شده است. + +دارید به نوشتن اولین خط کدتان نزدیک می‌شوید، زمان مناسبی برای دانلود یک ویرایشگر متن است! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/fa/code_editor/instructions.md b/fa/code_editor/instructions.md new file mode 100644 index 00000000000..74f829144e4 --- /dev/null +++ b/fa/code_editor/instructions.md @@ -0,0 +1,31 @@ +ویرایشگرهای مختلف زیادی وجود دارد که این امر به سلیقه شخصی برمی‌گردد. اغلب برنامه‌نویسان پایتون از محیط‌های توسعه یکپارچه (IDE, Integrated Development Environments) بسیار قدرتمند مثل PyCharm استفاده می‌کنند. اما برای یک مبتدی احتمالا خیلی مناسب نیست. پیشنهادهای ما به همان اندازه قدرتمند، اما بسیار ساده‌تر هستند. + +ما موارد زیر را پیشنهاد می‌کنیم، اما می‌توانید از مربی خود، ترجیحش را بپرسید. راحت‌تر است از مربی کمک بگیرید. + +## Gedit + +Gedit یک ویرایشگر متن باز و رایگان است که برای همه سیستم‌عاملها وجود دارد. + +[جهت دانلود کلیک نمایید](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[جهت دانلود کلیک نمایید](https://www.sublimetext.com/3) + +## Atom + +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. + +[جهت دانلود کلیک نمایید](https://atom.io/) + +## چرا ویرایشگر متن نصب می‌کنیم؟ + +ممکن است فکر کنید که چرا به جای استفاده از برنامه‌ای مثل Word یا Notepad، این نرم‌افزار خاص ویرایش کد را نصب می‌کنم. + +در ابتدا این که کدها نیاز دارند که به صورت متن ساده (**plain text**) باشند و مشکل برنامه‌هایی مثل Word یا Textedit این است که متن ساده تولید نمی‌کنند، بلکه متنی غنی (با فونت و قالب‌بندی) می‌سازند و از قالب‌های سفارشی مثل [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format) استفاده می‌کنند. + +دلیل دوم این است که ویرایشگرهای متن به طور خاص برای ویرایش کد ساخته شده‌اند. بنابراین، امکاناتی مثل رنگ‌آمیزی کدها بر اساس معنایشان یا بستن خودکار نقل قول‌ها را دارند. + +همه این‌ها را بعدا در عمل خواهیم دید. به زودی، شما به ویرایشگر خود به عنوان ابزار محبوبتان نگاه خواهید کرد. :) \ No newline at end of file diff --git a/fa/css/README.md b/fa/css/README.md new file mode 100644 index 00000000000..3d32c11c991 --- /dev/null +++ b/fa/css/README.md @@ -0,0 +1,304 @@ +# CSS – make it pretty! + +بلاگ ما هنوز خیلی زشت است، نه؟ وقتش است که زیبایش کنیم. برای این کار از CSS استفاده می‌کنیم. + +## CSS چیست؟ + +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? Once more, we'll use something that programmers released on the Internet for free. Reinventing the wheel is no fun, you know. + +## با بوت‌ استرپ شروع کنیم! + +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. Now it's developed by volunteers from all over the world! + +## نصب بوت استرپ + +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! + +![عدد 14.1](images/bootstrap1.png) + +ظاهری قشنگ تر از قبل! + +## فایل ها ی ثابت در جنگو + +ما در نهایت نگاهی دقیقتر به فایلها می اندازیم ( فایل های ثابت). فایلهای ثابت شامل تمامی فایلهای CSS و عکسها می باشند. Their content doesn't depend on the request context and will be the same for every user. + +### فایل های ثابت در جنگو کجا قرار میگیرد + +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 + │   └── templates + └── 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? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +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. 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 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 + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +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. :) 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 be overriden by 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 %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![عدد 14.2](images/color2.png) + +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 that to your CSS, save the file and see how it works! + +![عدد 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 + +``` + +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). + +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; + font-family: 'Lobster'; +} +``` + +![عدد 14.3](images/font.png) + +Great! + +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 + +``` + +And now add a class `post` to your `div` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, just copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```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 { + 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; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+
+

published: {{ post.published_date }}

+
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![عدد 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/fa/deploy/README.md b/fa/deploy/README.md new file mode 100644 index 00000000000..2c1ec41b377 --- /dev/null +++ b/fa/deploy/README.md @@ -0,0 +1,260 @@ +# فاز دیپلوی! + +> **توجه داشته باشید** که قسمت های پیش رو ممکن هست کمی سخت به نظر برسد. یکی از مهم ترین قسمت های توسعه وب سایت, دیپلوی می باشد. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ 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) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ 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 + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. We'll find out a bit more about static files later in the tutorial, when we edit the CSS for our site. + +Hit **Save** and then go back to the **Web** tab. + +We're all done! Hit the big green **Reload** button and you'll be able to go view your application. You'll find a link to it at the top of the page. + +## Debugging tips + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere [Web tab](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. Common problems include: + +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. + +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. + +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? + +- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6. + +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). + +And remember, your coach is here to help! + +# You are live! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet, just like that! \ No newline at end of file diff --git a/fa/deploy/install_git.md b/fa/deploy/install_git.md new file mode 100644 index 00000000000..f7a2fa418e5 --- /dev/null +++ b/fa/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). در بقیه موارد, پیش فرض ها مناسب هستند. استایل ویندوز را مورد بررسی قرار دهید ولی استایل یونیکس تا انتها مناسب می باشد و تغییر ندهید. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/fa/deploy/signup_pythonanywhere.md b/fa/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..ca66bd0de69 --- /dev/null +++ b/fa/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/fa/django/README.md b/fa/django/README.md new file mode 100644 index 00000000000..7f2ad03511a --- /dev/null +++ b/fa/django/README.md @@ -0,0 +1,27 @@ +# جنگو چیست؟ + +جنگو (جَنگو) یک فریم ورک تحت وب رایگان و open source است که با زبان پایتون نوشته شده است. یک فریم ورک تحت وب, دارای مجموعه ای است که به شما کمک می کنند تا یک وب سایت را سریع تر و راحت تر توسعه دهید. + +هنگامی که در حال ساخت یک وب سایت هستید، شما همیشه به مجموعه ای از اجزای مشابه نیاز دارید. به شرح زیر: یک روش برای کنترل کردن احراز هویت کاربر (ثبت نام ، ورود به حساب کاربری ، خروج از حساب کاربری) ، یک پنل مدیریت برای وب سایت خود ، فرم ها ، روشی برای آپلود فایل ها و غیره. + +خوشبختانه خیلی وقت پیش، افرادی متوجه این موضوع شدند که هنگام ساختن یک سایت جدید، توسعه دهندگان وب با مشکلات مشابهی روبرو می شوند، بنابراین آن ها تیمی را تشکیل دادند که به راحتی اجزای کار را در اختیار شما قرار می دهد که شما بتوانید به راحتی از انها استفاده کنید ودر نهایت فریم ورک ها را ساختند (جنگو یکی از آن هاست). + +فریم ورکها به این دلیل به وجود آمده اند که دیگر نیازی نباشد شما از اول چرخ را بسازید و به شما کمک می کند تا به راحتی سایت خود را بسازید. + +## چرا شما به یک فریم ورک نیاز دارید? + +برای درک بهترچگونگی عملکرد جنگو نگاه دقیق تری به سرور می اندازیم. اولین چیزی که سرور نیاز دارد که بداند این است که شما می خواهید سرور برای شما یک وب پیج را راه اندازی کند. + +حالا میل باکس را تصور کنید که برای دریافت نامه ها ( requests) چه کارهایی را انجام می دهد. این کار توسط وب سرور انجام خواهد گرفت. وب سرور نامه را خوانده و پاسخ مربوطه را به وب پیج می فرستد. اما هنگامی که شما میخواهید چیزی را ارسال کنید, شما به برخی مطالب نیاز دارید. و جنگو همونی است که به شما برای ایجاد محتوا کمک می کند. + +## زمانی که فردی یک درخواست از وب سایت به سرور شما می کند، چه اتفاقی می افتد؟ + +هنگامی که درخواست به وب سرور فرستاده می شود آن درخواست به جنگو انتقال داده می شود در این هنگام جنگو در تلاش برای فهمیدن درخواست می باشد. در ابتدا آدرس وب پیج را میگیرد و سعی در فهمیدن عملکرد می کند. این بخش توسط **urlresolver** جنگو انجام میگیرد (توجه داشته باشید که website address یوآرال را صدا میزند – Uniform Resource Locator– به این دلیل *urlresolver* نامیده می شود). یک لیست از الگوها را میگیرد و سعی برای مطابقت با آدرس می کند (خیلی منطقی نیست). Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +Of course, the description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will simply start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/fa/django_admin/README.md b/fa/django_admin/README.md new file mode 100644 index 00000000000..75faab2ce52 --- /dev/null +++ b/fa/django_admin/README.md @@ -0,0 +1,57 @@ +# پنل مدیریت در جنگو + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Login page](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/fa/django_forms/README.md b/fa/django_forms/README.md new file mode 100644 index 00000000000..3009f9cf445 --- /dev/null +++ b/fa/django_forms/README.md @@ -0,0 +1,447 @@ +# فرم در جنگو + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and, obviously, our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +It's time to open `blog/templates/blog/base.html`. We will add a link in `div` named `page-header`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will obviously see a familiar `NoReverseMatch` error, right? + +## URL + +We open `blog/urls.py` and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new form. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +Open `blog/templates/blog/post_detail.html` and add the line + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```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` we add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/topics/forms/ + +## Security + +Being able to create new posts just by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +In `blog/templates/blog/base.html`, find our `page-header` `div` and the anchor tag you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` tag to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to Github: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/fa/django_installation/README.md b/fa/django_installation/README.md new file mode 100644 index 00000000000..532f4da91ca --- /dev/null +++ b/fa/django_installation/README.md @@ -0,0 +1,7 @@ +# نصب و راه اندازی جنگو + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/fa/django_installation/instructions.md b/fa/django_installation/instructions.md new file mode 100644 index 00000000000..0bc080f7055 --- /dev/null +++ b/fa/django_installation/instructions.md @@ -0,0 +1,201 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directory and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** sometimes `source` might not be available. In those cases try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install --upgrade pip + + +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install django~=1.11.0 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) + Installing collected packages: django + Successfully installed django-1.11.3 + + + + +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/fa/django_models/README.md b/fa/django_models/README.md new file mode 100644 index 00000000000..a183f242112 --- /dev/null +++ b/fa/django_models/README.md @@ -0,0 +1,199 @@ +# مدل در جنگو + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (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 + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/fa/django_orm/README.md b/fa/django_orm/README.md new file mode 100644 index 00000000000..48c5a248d50 --- /dev/null +++ b/fa/django_orm/README.md @@ -0,0 +1,219 @@ +# جنگو ORM و QuerySets + +در این فصل شما چگونگی اتصال به پایگاه داده و ذخیره اطلاعات در آن را خواهید یادگرفت. وارد عمل شویم! + +## QuerySet چیست؟ + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +ساده ترین راه برای فراگیری با مثال است. پس شروع می کنیم.آماده اید؟ + +## پوسته Django + +کنسول های لوکال خود را باز کرده ( نه در PythonAnywhere) و این دستور را تایپ کنید: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + + +باید پاسخی مانند زیر دریافت کنید: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) >>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. + +### تمام اشیاء + +در ابتدا تمامی پست ها را نمایش می دهیم. با دستور زیر می توان این کار را انجام داد: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### ایجاد شیء + +به صورت زیر می توان یک شیء پست جدید در پایگاه داده ایجاد کرد: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +بیایید اول مدل User را وارد کنیم: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +مشاهده کاربران در پایگاه داده : + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. + +الان ما میتونیم پست خود را ایجا کنیم: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +با هم امتحان می کنیم. + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +اینگونه یک پست دیگر در لیست خواهیم داشت! + +### اضافه کردن پست های بیشتر + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### فیلتر کردن اشیاء + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. ما در اینجا به جای `all` از `filter` در تمامی `Post.objects.all()` استفاده می کنیم. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. الان یک کد به صورت زیر داریم: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +[, , , ] + +Context | Request Context +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` + +> دقت کنید که ۲تا کارکتر underscore ( ــ ) در میان `title` و `contains` وجود دارد. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +و حالا با متد `publish` آن را منتشر می کنیم: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### سفارش اشیاء (Ordering objects) + +QuerySets همچنین به شما اجازه میدهد لیستی از اشیاء را سفارش دهید.آنها را در قسمت `created_date` سفارش دهید: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +همچنین با اضافه کردن `-` در ابتدای دستور میتوانیم معکوس سفارش را ببینیم: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### زنجیرهای QuerySets + +شما همچنین می توانید QuerySets ها را با **chaining** با یکدیگر ترکیب کنید: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +این واقعا قدرتمند است و به شما اجازه کوءری های(queries) پیچیده را می دهد. + +موفق شدیم! شما الان برای قسمت بعدی آماده هستید. برای بستن پوسته (shell) دستور زیر را تایپ کنید: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +``` \ No newline at end of file diff --git a/fa/django_start_project/README.md b/fa/django_start_project/README.md new file mode 100644 index 00000000000..fe1abc7ca9a --- /dev/null +++ b/fa/django_start_project/README.md @@ -0,0 +1,202 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). + +Change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook, you'll always visit your test server by accessing: + +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![It worked!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/fa/django_templates/README.md b/fa/django_templates/README.md new file mode 100644 index 00000000000..892cef3b3db --- /dev/null +++ b/fa/django_templates/README.md @@ -0,0 +1,106 @@ +# templates در جنگو + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![عدد 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![عدد 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![عدد 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to Github + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +* 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! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![عدد 13.4](images/donut.png) \ No newline at end of file diff --git a/fa/django_urls/README.md b/fa/django_urls/README.md new file mode 100644 index 00000000000..c491b27de5c --- /dev/null +++ b/fa/django_urls/README.md @@ -0,0 +1,129 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is simply a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![Url](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + url(r'^admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Regex + +Do you wonder how Django matches URLs to views? Well, this part is tricky. Django uses `regex`, short for "regular expressions". Regex has a lot (a lot!) of rules that form a search pattern. Since regexes are an advanced topic, we will not go in detail over how they work. + +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: + +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern + +Anything else in the URL definition will be taken literally. + +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. + +Writing separate views for all the post numbers would be really annoying. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: + +* **^post/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\d+)** means that there will be a number (one or more digits) and that we want the number captured and extracted +* **/** tells django that another `/` character should follow +* **$** then indicates the end of the URL meaning that only strings ending with the `/` will match this pattern + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.conf.urls import include +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and look for further instructions there. + +Writing regular expressions in Python is always done with `r` in front of the string. This is a helpful hint for Python that the string may contain special characters that are not meant for Python itself, but for the regular expression instead. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views +``` + +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. That's correct, because in Django URL resolvers, 'http://127.0.0.1:8000/' is not a part of the URL. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Error](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/urls/ \ No newline at end of file diff --git a/fa/django_views/README.md b/fa/django_views/README.md new file mode 100644 index 00000000000..07afe091a52 --- /dev/null +++ b/fa/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Error](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/fa/dynamic_data_in_templates/README.md b/fa/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..6a70e71760f --- /dev/null +++ b/fa/dynamic_data_in_templates/README.md @@ -0,0 +1,81 @@ +# داده های پویا در templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py`. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/fa/extend_your_application/README.md b/fa/extend_your_application/README.md new file mode 100644 index 00000000000..190d32270fe --- /dev/null +++ b/fa/extend_your_application/README.md @@ -0,0 +1,197 @@ +# توسعه application شما + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, url, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. So far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique name for each record in a database. Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a number that increases by one for each record, i.e. 1, 2, 3) and adds it as a field named `pk` to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. The file should look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), +] +``` + +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: + +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. It means that Django will take everything that you place here and transfer it to a view as a variable called `pk`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` means that there needs to be one or more digits there. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? Of course: adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that we need to use exactly the same name as the one we specified in urls (`pk`). Omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But, of course, Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Page not found](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`. + +It will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ 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 %} + +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 --all . + $ git status + $ 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/): + +{% filename %}command-line{% endfilename %} + + $ cd my-first-blog + $ git pull + [...] + + +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. + +And that should be it! Congrats :) \ No newline at end of file diff --git a/fa/how_the_internet_works/README.md b/fa/how_the_internet_works/README.md new file mode 100644 index 00000000000..40b7dd70f2d --- /dev/null +++ b/fa/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# اینترنت چگونه کار می‌کند + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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. + +If you're not familiar with programming it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +OK, but you want to know how the Internet looks, right? + +We drew you a picture! It looks like this: + +![عدد 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: + +![عدد 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 https://djangogirls.org is saved) we need to pass a request through many, many different machines. + +It looks like this: + +![عدد 1.3](images/internet_2.png) + +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. + +![عدد 1.4](images/internet_4.png) + +That's how it works - 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 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, 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 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! \ No newline at end of file diff --git a/fa/html/README.md b/fa/html/README.md new file mode 100644 index 00000000000..4991c6014c5 --- /dev/null +++ b/fa/html/README.md @@ -0,0 +1,213 @@ +# آشنایی با HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(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 `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![عدد 11.1](images/step1.png) + +No error anymore! Congratulations :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Add the following to your template file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +

Hi there!

+

It works!

+ +``` + +So how does your website look now? Visit it to find out: http://127.0.0.1:8000/ + +![عدد 11.2](images/step3.png) + +It worked! Nice work there :) + +* 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![عدد 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `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, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```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.

+
+ + +``` + +We've created three `div` sections here. + +* 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: + +![عدد 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to Github + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% 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: + +{% filename %}command-line{% endfilename %} + + $ git add --all . + + +> **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): + +{% 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. + +{% 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: + +{% 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 + $ git pull + [...] + + +And watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **Files tab** and view your code on PythonAnywhere. + +* 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. :) \ No newline at end of file diff --git a/fa/install_git.md b/fa/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/fa/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/fa/installation/README.md b/fa/installation/README.md new file mode 100644 index 00000000000..318ffbfb40f --- /dev/null +++ b/fa/installation/README.md @@ -0,0 +1,58 @@ +# 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 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) + +* [آشنایی با پایتون](../python_introduction/README.md) + +* [جنگو چیست؟](../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. \ No newline at end of file diff --git a/fa/instructions.md b/fa/instructions.md new file mode 100644 index 00000000000..b5a0981698b --- /dev/null +++ b/fa/instructions.md @@ -0,0 +1,31 @@ +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. :) \ No newline at end of file diff --git a/fa/intro_to_command_line/README.md b/fa/intro_to_command_line/README.md new file mode 100644 index 00000000000..35cfbeb4a08 --- /dev/null +++ b/fa/intro_to_command_line/README.md @@ -0,0 +1,429 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +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. :) + +> 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 by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% 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 + ... + + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Create directory + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% 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? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, huh? :) + +## سرفصل ها + +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** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| 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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Ready? + +Let's dive into Python! \ No newline at end of file diff --git a/fa/python_installation/README.md b/fa/python_installation/README.md new file mode 100644 index 00000000000..3ea387325cb --- /dev/null +++ b/fa/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# نصب و راه اندازی پایتون + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/fa/python_installation/instructions.md b/fa/python_installation/instructions.md new file mode 100644 index 00000000000..31cde2d0baf --- /dev/null +++ b/fa/python_installation/instructions.md @@ -0,0 +1,106 @@ +> 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.6, 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, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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.6 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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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-361/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.6.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.6.1 + + +If you have a different 'micro version' of Python installed, e.g. 3.6.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.6 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python 3.6.1 + + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + +* * * + +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. \ No newline at end of file diff --git a/fa/python_introduction/README.md b/fa/python_introduction/README.md new file mode 100644 index 00000000000..ec2834af04f --- /dev/null +++ b/fa/python_introduction/README.md @@ -0,0 +1,1061 @@ +# آشنایی با پایتون + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.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. + +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. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, simply type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### سرفصل ها + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Errors + +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`: + +{% 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? + +{% 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? + +## Variables + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% 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! + +{% 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Dictionaries + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% 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 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +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: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `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: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 learned another amazing thing. + +### سرفصل ها + +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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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 + +{% 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!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, just ask for help. + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single `tab` will also count as 4 spaces. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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. + +### سرفصل ها + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. This is because Python reads the file and executes it from top to bottom. So in order to use our function, we have to re-write it at the bottom. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% 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: + +{% 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: + +{% 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: + +{% 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! + +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 + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 by that we mean it includes the first value, but not the last. + +## سرفصل ها + +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. :) + +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/fa/signup_pythonanywhere.md b/fa/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/fa/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/fa/template_extending/README.md b/fa/template_extending/README.md new file mode 100644 index 00000000000..0b70f067b35 --- /dev/null +++ b/fa/template_extending/README.md @@ -0,0 +1,147 @@ +# توسعه template + +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. + +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 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 + + +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 %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +But why? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. 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' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/fa/whats_next/README.md b/fa/whats_next/README.md new file mode 100644 index 00000000000..37f4e0440b8 --- /dev/null +++ b/fa/whats_next/README.md @@ -0,0 +1,25 @@ +# گام بعدی چیست؟ + +از پسش بر اومدی! **ایول داری**. ما بهت افتخار می کنیم! <3 + +### حالا چیکار کنم؟ + +یک نفس راحت بکش. همین حالا هم ی کار بزرک کردی. + +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. + +### شما می تونید یک منبع دیگه معرفی کنید؟ + +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 the resources listed below. They're all very recommended! + +- [Django's official tutorial](https://docs.djangoproject.com/en/1.11/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://www.gettingstartedwithdjango.com/) +- [Two Scoops of Django 1.11: Best Practices for Django Web Framework book](https://www.twoscoopspress.com/products/two-scoops-of-django-1-11) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) - you can also request a free eBook licence by contacting the author Tracy Osborn at \ No newline at end of file diff --git a/fi-FI/GLOSSARY.md b/fi-FI/GLOSSARY.md new file mode 100644 index 00000000000..0e87d991ae8 --- /dev/null +++ b/fi-FI/GLOSSARY.md @@ -0,0 +1,3 @@ +# koodi muokkaaja + +Koodi muokkaaja on sovellus, joka antaa sinun tallentaa koodisi, jotta voit jatkaa sitä myöhemmin. You can learn where to get one from the [Code editor chapter](./code_editor/README.md) \ No newline at end of file diff --git a/fi-FI/README.md b/fi-FI/README.md new file mode 100644 index 00000000000..3707450b472 --- /dev/null +++ b/fi-FI/README.md @@ -0,0 +1,51 @@ +# Django tytöt tutoriaali + +[![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/ + +## Tervetuloa + +Welcome to the Django Girls Tutorial! We are happy to see you here. :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine. :) + +## Johdanto + +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? Have you ever wondered how to create a website but have never had enough motivation to start? Have you ever thought that the software world is too complicated for you to even try doing something on your own? + +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. + +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! + +## What will you learn during the tutorial? + +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! + +It will (more or less) look like this: + +![Kuva 0.1](images/application.png) + +> 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. + +## About and contributing + +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 into other languages? + +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](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/fi-FI/SUMMARY.md b/fi-FI/SUMMARY.md new file mode 100644 index 00000000000..95ae8ec5b1e --- /dev/null +++ b/fi-FI/SUMMARY.md @@ -0,0 +1,35 @@ +# Yhteenveto + +* [Johdanto](README.md) +* [Asennus](installation/README.md) + * [Command Line](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Code Editor](installation/README.md#code-editor) + * [Virtual Environment](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Installation (chromebook)](chromebook_setup/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) +* [Mikä on Django?](django/README.md) +* [Django installation](django_installation/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) +* [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) +* [Template extending](template_extending/README.md) +* [Extend your application](extend_your_application/README.md) +* [Django Forms](django_forms/README.md) +* [Mitä seuraavaksi?](whats_next/README.md) \ No newline at end of file diff --git a/fi-FI/chromebook_setup/README.md b/fi-FI/chromebook_setup/README.md new file mode 100644 index 00000000000..03249a84d41 --- /dev/null +++ b/fi-FI/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook setup + +> **Note** If you already worked through the [installation steps](../installation/README.md), 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/fi-FI/chromebook_setup/instructions.md b/fi-FI/chromebook_setup/instructions.md new file mode 100644 index 00000000000..e39cebb863b --- /dev/null +++ b/fi-FI/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Voit [ohittaa tämän osan](http://tutorial.djangogirls.org/en/installation/#install-python), jos et käytä Chromebookia. Jos et käytä, asennuskokemus on hieman erilainen. Voit ohittaa loput asennusohjeet. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Cloud IDE (Integroitu kehitysympäristö) on työkalu, jolla saat käyttöösi koodieditorin ja pääset netissä toimivaan tietokoneeseen, johon voit asentaa, kirjoittaa ja käyttää ohjelmistoa. For the duration of the tutorial, cloud IDE 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 IDE sets up for you. Here are the instructions for cloud IDEs (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). You can choose one of the cloud IDEs, and follow the instruction of the cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Go to [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Sign up for an account +3. Click *New Server* and choose the Django app +4. Click Terminal button(on the left side of the window) + +Now you should see an interface with a sidebar, buttons at the left. Click "Terminal" button to open terminal window with prompt like this: + +{% filename %}Terminal{% endfilename %} + + $ + + +The terminal on the PaizaCloud Cloud IDE is prepared for your instructions. You can resize or maximize that window to make it a bit bigger. + +#### AWS Cloud9 + +Currently Cloud 9 requires you to sign up with AWS and enter credit card information. + +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) and click *Get started with AWS Cloud9* +3. Sign up for an AWS account (requires credit card information, but you can use it for free) +4. In the AWS Dashboard, enter *Cloud9* in the search bar and click it +5. In the Cloud 9 dashboard, click *Create environment* +6. Name it *django-girls* +7. While configuring settings, select *Create a new instance for environment (EC2)* for "Environment Type" and the *t2.micro* "Instance type" (it should say "Free-tier eligible."). The default cost-saving setting is fine and you can keep the other defaults. +8. Click *Next step* +9. Click *Create environment* + +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 %}bash{% endfilename %} + + yourusername:~/workspace $ + + +This bottom area is your terminal. You can use the terminal to send instructions to the remote Cloud 9 computer. You can resize that window to make it a bit bigger. + +#### Glitch.com Cloud IDE + +1. Go to [Glitch.com](https://glitch.com/) +2. Sign up for an account (https://glitch.com/signup) or use your GitHub account if you have one. (See GitHub instructions below.) +3. Click *New Project* and choose *hello-webpage* +4. Click on the Tools dropdown list (at the bottom left side of the window), then on Terminal button to open terminal tab with a prompt like this: + +{% filename %}Terminal{% endfilename %} + + app@name-of-your-glitch-project:~ + + +When using Glitch.com as your Cloud IDE, you don't have to create a virtual environment. Instead, create the following files manually: + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Once these files are created, go to the Terminal and execute the following commands to create your first Django project: + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +In order to see detailed error messages, you can activate Django debug logs for your Glitch application. Simply add the following at the end of the `mysite/settings.py` file. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +This will create a `debug.log` file detailing Django operations and any error messages that might come up, making it much easier to fix if your website does not work. + +The initial restarting of the Glitch project should fail. (If you click on the top dropdown button `Show` then click on `In a New Window`, you will receive a `DisallowedHost` error message.) Do not worry about it at this stage, the tutorial will fix this as soon as you update the Django settings of your project in the `mysite/settings.py` file. + +### Virtuaaliympäristö + +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. + +Run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(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 for 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). \ No newline at end of file diff --git a/fi-FI/code_editor/README.md b/fi-FI/code_editor/README.md new file mode 100644 index 00000000000..0a401fb1f52 --- /dev/null +++ b/fi-FI/code_editor/README.md @@ -0,0 +1,11 @@ +# Code editor + +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + +You're about to write your first line of code, so it's time to download a code editor! + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. The cloud IDE you chose (PaizaCloud Cloud IDE or AWS Cloud9) includes a code editor, and when you open a file in your IDE from the File menu, you will automatically be using the editor. +> +> **Note** You might have done this earlier in the [Installation chapter](../installation/README.md) – if so, you can skip right ahead to the next chapter! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/fi-FI/code_editor/instructions.md b/fi-FI/code_editor/instructions.md new file mode 100644 index 00000000000..69f0525c394 --- /dev/null +++ b/fi-FI/code_editor/instructions.md @@ -0,0 +1,37 @@ +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. + +## Visual Studio Code + +Visual Studio Code is a source code editor developed by Microsoft for Windows, Linux and macOS. It includes support for debugging, embedded Git control, syntax highlighting, intelligent code completion, snippets, and code refactoring. + +[Lataa se täältä](https://code.visualstudio.com/) + +## Gedit + +Gedit is an open-source, free editor, available for all operating systems. + +[Lataa se täältä](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. + +[Lataa se täältä](https://www.sublimetext.com/3) + +## Atom + +Atom is another popular editor. It's free, open-source and available for Windows, OS X and Linux. Atom is developed by [GitHub](https://github.com/). + +[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. :) \ No newline at end of file diff --git a/fi-FI/css/README.md b/fi-FI/css/README.md new file mode 100644 index 00000000000..1250be8258f --- /dev/null +++ b/fi-FI/css/README.md @@ -0,0 +1,330 @@ +# CSS – make it pretty! + +Our blog still looks pretty ugly, right? Time to make it nice! We will use CSS for that. + +## Mikä on CSS? + +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? 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: https://getbootstrap.com/ + +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, open up your `.html` file in the code editor and add this to the `` section: + +{% 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. So go ahead, open your website and refresh the page. Here it is! + +![Kuva 14.1](images/bootstrap1.png) + +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. Their content doesn't depend on the request context and will be the same for every user. + +### Where to put static files for Django + +Django already knows where to find the static files for the built-in "admin" app. Now we 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 + │   └── templates + └── 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. Valmis? + + 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. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. + +But let's do at least a little. Maybe we could change the color of our headers? 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, h2 a { + color: #C25100; +} + +``` + +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element; the `h2 a` selector does the same thing for `h2` elements. 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 `#C25100`, which is a dark orange. Or you can put your own color here, but make sure it has good contrast against a white background! + +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 element by using the element name `a`, the class `external_link`, or the id `link_to_wiki_page`: + +```html + +``` + +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). + +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file in the code editor and add this line at the very beginning of it: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +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 be overriden by 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 static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, save the file and refresh the site! + +![Kuva 14.2](images/color2.png) + +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 that to your CSS, save the file and see how it works! + +![Kuva 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 + +``` + +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). + +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, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Kuva 14.3](images/font.png) + +Great! + +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. Replace the `header` that contains your header with the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +And now add a class `post` to your `article` containing a blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +We will now add declaration blocks to different selectors. Selectors starting with `.` relate to classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. For now, copy and paste it into your `blog/static/css/blog.css` file: + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Then surround the HTML code which displays the posts with declarations of classes. Replace this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +in the `blog/templates/blog/post_list.html` with this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Save those files and refresh your website. + +![Kuva 14.4](images/final.png) + +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? + +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! + +We really recommend taking the free online courses "Basic HTML & HTML5" and "Basic CSS" on [freeCodeCamp](https://learn.freecodecamp.org/). They can help you learn all about making your websites prettier with HTML and CSS. + +Ready for the next chapter?! :) \ No newline at end of file diff --git a/fi-FI/deploy/README.md b/fi-FI/deploy/README.md new file mode 100644 index 00000000000..cc2d165200c --- /dev/null +++ b/fi-FI/deploy/README.md @@ -0,0 +1,246 @@ +# Deploy! + +> **Note** The following chapter can be sometimes a bit hard to get through. Persist and finish it; deployment is an important part of the website development process. This chapter is placed in the middle of the tutorial so that your mentor can help with the slightly trickier process of getting your website online. This means you can still finish the tutorial on your own if you run out of time. + +Until now, your website was only available on your computer. Now you will learn how to deploy it! Deploying is the process of publishing your application on the Internet so people can finally go and see your app. :) + +As you learned, a website has to be located on a server. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. + +The other external service we'll be using is [GitHub](https://www.github.com), which is a code hosting service. There are others out there, but almost all programmers have a GitHub account these days, and now so will you! + +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. + +# Git + +> **Note** If you already did the [installation steps](../installation/README.md), there's no need to do this again – you can skip to the next section and start creating your Git repository. + +{% include "/deploy/install_git.md" %} + +## Starting our Git repository + +Git tracks changes to a particular set of files in what's called a code repository (or "repo" for short). Let's start one for our project. Open up your console and run these commands, in the `djangogirls` directory: + +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. You should be in the `djangogirls` folder. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). + +Git will track changes to all the files and folders in this directory, but there are some files we want it to ignore. We do this by creating a file called `.gitignore` in the base directory. Open up your editor and create a new file with the following contents: + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Database + db.sqlite3 + + # Static folder at project root + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + +And save it as `.gitignore` in the "djangogirls" folder. + +> **Note** The dot at the beginning of the file name is important! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. And be sure not to add `.txt`, `.py`, or any other extension to the file name -- it will only be recognized by Git if the name is just `.gitignore`. Linux and MacOS treat files with a name that starts with `.` (such as `.gitignore`) as hidden and the normal `ls` command won't show these files. Instead use `ls -a` to see the `.gitignore` file. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your users and posts are stored. We'll follow standard web programming practice, meaning that we'll use separate databases for your local testing site and your live website on PythonAnywhere. The PythonAnywhere database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts and superuser you created so far are going to only be available locally, and you'll have to create new ones on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. + +It's a good idea to use a `git status` command before `git add` or whenever you find yourself unsure of what has changed. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +And finally we save our changes. Go to your console and run these commands: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pushing your code to GitHub + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) Be sure to remember your password (add it to your password manager, if you use one). + +Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + +![](images/new_github_repo.png) + +> **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to stick with the name `my-first-blog`. + +On the next screen, you'll be shown your repo's clone URL, which you will use in some of the commands that follow: + +![](images/github_get_repo_url_screenshot.png) + +Now we need to hook up the Git repository on your computer to the one up on GitHub. + +Type the following into your console (replace `` with the username you entered when you created your GitHub account, but without the angle-brackets -- the URL should match the clone URL you just saw): + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +When you push to GitHub, you'll be asked for your GitHub username and password (either right there in the command-line window or in a pop-up window), and after entering credentials you should see something like this: + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Your code is now on GitHub. Go and check it out! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + +# Setting up our blog on PythonAnywhere + +## Sign up for a PythonAnywhere account + +> **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configuring our site on PythonAnywhere + +Go back to the main [PythonAnywhere Dashboard](https://www.pythonanywhere.com/) by clicking on the logo, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command line, just like the one on your computer. + +![The 'New Console' section on the PythonAnywhere web interface, with a button for 'bash'](images/pythonanywhere_bash_console.png) + +> **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + +Deploying a web app on PythonAnywhere involves pulling down your code from GitHub, and then configuring PythonAnywhere to recognise it and start serving it as a web application. There are manual ways of doing it, but PythonAnywhere provides a helper tool that will do it all for you. Let's install it first: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +That should print out some things like `Collecting pythonanywhere`, and eventually end with a line saying `Successfully installed (...) pythonanywhere- (...)`. + +Now we run the helper to automatically configure our app from GitHub. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of ``, so that the URL matches the clone URL from GitHub): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +As you watch that running, you'll be able to see what it's doing: + +- Downloading your code from GitHub +- Creating a virtualenv on PythonAnywhere, just like the one on your own computer +- Updating your settings file with some deployment settings +- Setting up a database on PythonAnywhere using the `manage.py migrate` command +- Setting up your static files (we'll learn about these later) +- And configuring PythonAnywhere to serve your web app via its API + +On PythonAnywhere all those steps are automated, but they're the same steps you would have to go through with any other server provider. + +The main thing to notice right now is that your database on PythonAnywhere is actually totally separate from your database on your own computer, so it can have different posts and admin accounts. As a result, just as we did on your own computer, we need to initialize the admin account with `createsuperuser`. PythonAnywhere has automatically activated your virtualenv for you, so all you need to do is run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Type in the details for your admin user. Best to use the same ones as you're using on your own computer to avoid any confusion, unless you want to make the password on PythonAnywhere more secure. + +Now, if you like, you can also take a look at your code on PythonAnywhere using `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +You can also go to the "Files" page and navigate around using PythonAnywhere's built-in file browser. (From the Console page, you can get to other PythonAnywhere pages from the menu button in the upper right corner. Once you're on one of the pages, there are links to the other ones near the top.) + +## You are now live! + +Your site should now be live on the public Internet! Click through to the PythonAnywhere "Web" page to get a link to it. You can share this with anyone you want. :) + +> **Note** This is a beginners' tutorial, and in deploying this site we've taken a few shortcuts which aren't ideal from a security point of view. If and when you decide to build on this project, or start a new project, you should review the [Django deployment checklist](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) for some tips on securing your site. + +## Debugging tips + +If you see an error while running the `pa_autoconfigure_django.py` script, here are a few common causes: + +- Forgetting to create your PythonAnywhere API token. +- Making a mistake in your GitHub URL +- If you see an error saying *"Could not find your settings.py"*, it's probably because you didn't manage to add all your files to Git, and/or you didn't push them up to GitHub successfully. Have another look at the Git section above +- If you previously signed up for a PythonAnywhere account and had an error with collectstatic, you probably have an older version of SQLite (eg 3.8.2) for your account. In that case, sign up for a new account and try the commands in the PythonAnywhere section above. + +If you see an error when you try to visit your site, the first place to look for some debugging info is in your **error log**. You'll find a link to this on the PythonAnywhere ["Web" page](https://www.pythonanywhere.com/web_app_setup/). See if there are any error messages in there; the most recent ones are at the bottom. + +There are also some [general debugging tips on the PythonAnywhere help site](http://help.pythonanywhere.com/pages/DebuggingImportError). + +And remember, your coach is here to help! + +# Check out your site! + +The default page for your site should say "It worked!", just like it does on your local computer. Try adding `/admin/` to the end of the URL, and you'll be taken to the admin site. Log in with the username and password, and you'll see you can add new Posts on the server -- remember, the posts from your local test database were not sent to your live blog. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? + +Give yourself a *HUGE* pat on the back! Server deployments are one of the trickiest parts of web development and it often takes people several days before they get them working. But you've got your site live, on the real Internet! \ No newline at end of file diff --git a/fi-FI/deploy/install_git.md b/fi-FI/deploy/install_git.md new file mode 100644 index 00000000000..53fbe28d617 --- /dev/null +++ b/fi-FI/deploy/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in word processor programs (e.g., Microsoft Word or LibreOffice Writer), but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for two: in the step where it asks to choose your editor, you should pick Nano, and in the step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or PowerShell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/fi-FI/deploy/signup_pythonanywhere.md b/fi-FI/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..555e36731dd --- /dev/null +++ b/fi-FI/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere is a service for running Python code on servers "in the cloud". We'll use it for hosting our site, live and on the Internet. + +We will be hosting the blog we're building on PythonAnywhere. Sign up for a "Beginner" account on PythonAnywhere (the free tier is fine, you don't need a credit card). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![The PythonAnywhere signup page showing button to create a free 'Beginner' account](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. Also, be sure to remember your password (add it to your password manager, if you use one). + +## Creating a PythonAnywhere API token + +This is something you only need to do once. When you've signed up for PythonAnywhere, you'll be taken to your dashboard. Find the link near the top right to your "Account" page: + +![Account link on the top right on the page](../deploy/images/pythonanywhere_account.png) + +then select the tab named "API token", and hit the button that says "Create new API token". + +![The API token tab on the Account page](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/fi-FI/django/README.md b/fi-FI/django/README.md new file mode 100644 index 00000000000..278131d480d --- /dev/null +++ b/fi-FI/django/README.md @@ -0,0 +1,27 @@ +# Mikä on Django? + +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) on ilmainen avoimen lähdekoodin web-sovelluskehys, joka on kirjoitetty Pythonilla. Web-sovelluskehys on joukko komponentteja, jotka auttavat kehittämään verkkosivustoja nopeammin ja helpommin. + +Kun olet rakentamassa sivustoa, tarvitset aina samanlaisia komponentteja: tavan käsitellä käyttäjän todennus (rekisteröitymisessä sekä sisään ja ulos kirjautuessa), hallinto-paneelin, lomakkeita, tavan ladata tiedostoja jne. + +Onneksi ihmiset jo kauan sitten huomasivat, että web-kehittäjät kohtaavat kerta toisensa jälkeen samanlaisia ongelmia uutta sivustoa rakentaessaan, joten he yhdistivät voimansa ja loivat sovelluskehyksiä (esimerkiksi Djangon), jotka antavat valmiita komponentteja suoraan käyttöön. + +Sovelluskehykset ovat olemassa, jotta sinun ei tarvitsisi keksiä pyörää uudelleen ja jotta säästät aikaa rakentaessasi uutta sivustoa. + +## Why do you need a framework? + +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. + +Imagine a mailbox (port) which is monitored for incoming letters (requests). This is done by a web server. The web server reads the letter and then sends a response with a webpage. But when you want to send something, you need to have some content. And Django is something that helps you create the content. + +## What happens when someone requests a website from your server? + +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). + +Imagine a mail carrier with a letter. She is walking down the street and checks each house number against the one on the letter. If it matches, she puts the letter there. This is how the urlresolver works! + +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Maybe the user asked to change something in the data? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. + +The description above is a little bit simplified, but you don't need to know all the technical things yet. Having a general idea is enough. + +So instead of diving too much into details, we will start creating something with Django and we will learn all the important parts along the way! \ No newline at end of file diff --git a/fi-FI/django_admin/README.md b/fi-FI/django_admin/README.md new file mode 100644 index 00000000000..72f6b892ca5 --- /dev/null +++ b/fi-FI/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +To add, edit and delete the posts we've just modeled, we will use Django admin. + +Let's open the `blog/admin.py` file in the code editor and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +As you can see, we import (include) the Post model defined in the previous chapter. To make our model visible on the admin page, we need to register the model with `admin.site.register(Post)`. + +OK, time to look at our Post model. Remember to run `python manage.py runserver` in the console to run the web server. Go to your browser and type the address http://127.0.0.1:8000/admin/. You will see a login page like this: + +![Kirjautumissivu](images/login_page2.png) + +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. + +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. + +![Django admin](images/django_admin3.png) + +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content –- it's only visible to you on your local computer -- you can copy-paste some text from this tutorial to save time. :) + +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. + +![Django admin](images/edit_post3.png) + +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/ + +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/fi-FI/django_forms/README.md b/fi-FI/django_forms/README.md new file mode 100644 index 00000000000..68676f99fa5 --- /dev/null +++ b/fi-FI/django_forms/README.md @@ -0,0 +1,479 @@ +# Django Forms + +The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's `admin` is cool, but it is rather hard to customize and make pretty. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! + +The nice thing about Django forms is that we can either define one from scratch or create a `ModelForm` which will save the result of the form to the model. + +This is exactly what we want to do: we will create a form for our `Post` model. + +Like every important part of Django, forms have their own file: `forms.py`. + +We need to create a file with this name in the `blog` directory. + + blog + └── forms.py + + +OK, let's open it in the code editor and type the following code: + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +We need to import Django forms first (`from django import forms`) and our `Post` model (`from .models import Post`). + +`PostForm`, as you probably suspect, is the name of our form. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. + +Next, we have `class Meta`, where we tell Django which model should be used to create this form (`model = Post`). + +Finally, we can say which field(s) should end up in our form. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? + +And that's it! All we need to do now is use the form in a *view* and display it in a template. + +So once again we will create a link to the page, a URL, a view and a template. + +## Link to a page with the form + +Before we add the link, we need some icons to use as buttons for the link. For this tutorial, download [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) and save it in the folder `blog/templates/blog/icons/` + +> Note: To download the SVG image, open the context menu on the link (usually by right-clicking on it) and select "Save link as". In the dialog asking you where to save the file, navigate to the `djangogirls` directory of your Django project, and within that to subdirectory `blog/templates/blog/icons/`, and save the file there. + +It's time to open `blog/templates/blog/base.html` in the code editor. Now we can use this icon file inside the base template as follows. In the `div` element inside `header` section, we will add a link before the `h1` element: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Note that we want to call our new view `post_new`. The [SVG icon](https://icons.getbootstrap.com/icons/file-earmark-plus/) is provided by the [Bootstrap Icons](https://icons.getbootstrap.com/) and it will display a page icon with plus sign. We use a Django template directive called `include`. This will inject the file's content into the Django template. The web browser knows how to handle this type of content without any further processing. + +> You can download all the Bootstrap icons [here](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Unzip the file and copy all the SVG image files into a new folder inside `blog/templates/blog/` called `icons`. That way you can access an icon like `pencil-fill.svg` using the file path `blog/templates/blog/icons/pencil-fill.svg` + +After editing the line, your HTML file should now look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +After saving and refreshing the page http://127.0.0.1:8000 you will see a familiar `NoReverseMatch` error. Is that the case? Good! + +## URL + +We open `blog/urls.py` in the code editor and add a line: + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +And the final code will look like this: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. + +## post_new view + +Time to open the `blog/views.py` file in the code editor and add the following lines with the rest of the `from` rows: + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To create a new `Post` form, we need to call `PostForm()` and pass it to the template. We will go back to this *view*, but for now, let's quickly create a template for the form. + +## Template + +We need to create a file `post_edit.html` in the `blog/templates/blog` directory, and open it in the code editor. To make a form work we need several things: + +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form element: `...`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. This is very important, since it makes your forms secure! If you forget about this bit, Django will complain when you try to save the form: + +![CSFR Forbidden page](images/csrf2.png) + +OK, so let's see how the HTML in `post_edit.html` should look: + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Time to refresh! Yay! Your form is displayed! + +![New form](images/new_form2.png) + +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? + +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? + +The answer is: nothing. We need to do a little bit more work in our *view*. + +## Saving the form + +Open `blog/views.py` once again in the code editor. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `
` definition had the variable `method="POST"`? All the fields from the form are now in `request.POST`. You should not rename `POST` to anything else (the only other valid value for `method` is `GET`, but we have no time to explain what the difference is). + +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. So we need to add a condition (we will use `if` for that): + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. + +We check if the form is valid and if so, we can save it! + +{% filename %}blog/views.py{% endfilename %} + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Basically, we have two things here: we save the form with `form.save` and we add an author (since there was no `author` field in the `PostForm` and this field is required). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! + +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more import: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail` is the name of the view we want to go to. Remember that this *view* requires a `pk` variable? To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Let's see if it works. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! + +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. + +That is awesome! + +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. This will fix the issue temporarily. There is a permanent fix awaiting you in the **Homework: add security to your website!** chapter after the main tutorial. + +![Logged in error](images/post_create_error.png) + +## Form validation + +Now, we will show you how cool Django forms are. A blog post needs to have `title` and `text` fields. In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. + +Try to save the form without `title` and `text`. Guess what will happen! + +![Form validation](images/form_validation2.png) + +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? + +## Edit form + +Now we know how to add a new post. But what if we want to edit an existing one? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) + +First, let's save the icon which represents the edit button. Download [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) and save it to the location `blog/templates/blog/icons/`. + +Open `blog/templates/blog/post_detail.html` in the code editor and add the following code inside `article` element: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Open `blog/urls.py` in the code editor, and add this line: + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//edit/', views.post_edit, name='post_edit'), +``` + +We will reuse the template `blog/templates/blog/post_edit.html`, so the last missing thing is a *view*. + +Let's open `blog/views.py` in the code editor and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +This looks almost exactly the same as our `post_new` view, right? But not entirely. For one, we pass an extra `pk` parameter from `urls`. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: + +![Edit button](images/edit_button2.png) + +When you click it you will see the form with our blog post: + +![Edit form](images/edit_form2.png) + +Feel free to change the title or the text and save the changes! + +Congratulations! Your application is getting more and more complete! + +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Security + +Being able to create new posts by clicking a link is awesome! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. + +Open `blog/templates/blog/base.html` in the code editor, find our `div` inside `header` and the anchor element you put in there earlier. It should look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Change the `` element to look like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. This doesn't protect the creation of new posts completely, but it's a good first step. We'll cover more security in the extension lessons. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` in the code editor and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Change it to this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! + +## One more thing: deploy time! + +Let's see if all this works on PythonAnywhere. Time for another deploy! + +* First, commit your new code, and push it up to GitHub: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + + +* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (use the menu button in the upper right of the console) and hit **Reload**. Refresh your https://subdomain.pythonanywhere.com blog to see the changes. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/fi-FI/django_installation/README.md b/fi-FI/django_installation/README.md new file mode 100644 index 00000000000..9b024008342 --- /dev/null +++ b/fi-FI/django_installation/README.md @@ -0,0 +1,7 @@ +# Django installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md) then you've already done this – you can go straight to the next chapter! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/fi-FI/django_installation/instructions.md b/fi-FI/django_installation/instructions.md new file mode 100644 index 00000000000..fc965146844 --- /dev/null +++ b/fi-FI/django_installation/instructions.md @@ -0,0 +1,229 @@ +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +## Virtual environment + +Before we install Django we will get you to install an extremely useful tool to help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended. Starting with the best possible setup will save you a lot of trouble in the future! + +So, let's create a **virtual environment** (also called a *virtualenv*). Virtualenv will isolate your Python/Django setup on a per-project basis. This means that any changes you make to one website won't affect any others you're also developing. Neat, right? + +All you need to do is find a directory in which you want to create the `virtualenv`; your home directory, for example. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. + +For this tutorial we will be using a new directory `djangogirls` from your home directory: + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +We will make a virtualenv called `myvenv`. The general command will be in the format: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Where `myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces, accents or special characters. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + +`myvenv` is the name of your `virtualenv`. You can use any other name, but stick to lowercase and use no spaces. It is also a good idea to keep the name short as you'll be referencing it a lot! + +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> To get around this, use the `virtualenv` command instead. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Working with virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> The advantage is that you don't have to switch between editor windows and command-line windows + + + + + +Start your virtual environment by running: + +{% filename %}command-line{% endfilename %} + + $ source myvenv/bin/activate + + +Remember to replace `myvenv` with your chosen `virtualenv` name! + +> **NOTE:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. + +When working within a virtual environment, `python` will automatically refer to the correct version so you can use `python` instead of `python3`. + +OK, we have all important dependencies in place. We can finally install Django! + +## Installing Django {#django} + +Now that you have your `virtualenv` started, you can install Django. + +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installing packages with requirements + +A requirements file keeps a list of dependencies to be installed using `pip install`: + +First create a `requirements.txt` file inside of the `djangogirls/` folder, using the code editor that you installed earlier. You do this by opening a new file in the code editor and then saving it as `requirements.txt` in the `djangogirls/` folder. Your directory will look like this: + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +In your `djangogirls/requirements.txt` file you should add the following text: + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Now, run `pip install -r requirements.txt` to install Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> If you get an error when calling pip on Ubuntu 12.04 please run `python -m pip install -U --force-reinstall pip` to fix the pip installation in the virtualenv. + + + +That's it! You're now (finally) ready to create a Django application! \ No newline at end of file diff --git a/fi-FI/django_models/README.md b/fi-FI/django_models/README.md new file mode 100644 index 00000000000..f2a68a8727f --- /dev/null +++ b/fi-FI/django_models/README.md @@ -0,0 +1,201 @@ +# Django models + +What we want to create now is something that will store all the posts in our blog. But to be able to do that we need to talk a little bit about things called `objects`. + +## Objects + +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. + +So what is an object? It is a collection of properties and actions. It sounds weird, but we will give you an example. + +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). + +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +So basically the idea is to describe real things in code with properties (called `object properties`) and actions (called `methods`). + +How will we model blog posts then? We want to build a blog, right? + +We need to answer the question: What is a blog post? What properties should it have? + +Well, for sure our blog post needs some text with its content and a title, right? It would be also nice to know who wrote it – so we need an author. Finally, we want to know when the post was created and published. + + Post + -------- + title + text + author + created_date + published_date + + +What kind of things could be done with a blog post? It would be nice to have some `method` that publishes the post, right? + +So we will need a `publish` method. + +Since we already know what we want to achieve, let's start modeling it in Django! + +## Django model + +Knowing what an object is, we can create a Django model for our blog post. + +A model in Django is a special kind of object – it is saved in the `database`. A database is a collection of data. This is a place in which you will store information about users, your blog posts, etc. We will be using a SQLite database to store our data. This is the default Django database adapter – it'll be enough for us right now. + +You can think of a model in the database as a spreadsheet with columns (fields) and rows (data). + +### Creating an application + +To keep everything tidy, we will create a separate application inside our project. It is very nice to have everything organized from the very beginning. To create an application we need to run the following command in the console (from `djangogirls` directory where `manage.py` file is): + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py` -- open it in your code editor. We need to find `INSTALLED_APPS` and add a line containing `'blog.apps.BlogConfig',` just above `]`. So the final product should look like this: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### Creating a blog post model + +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. + +Let's open `blog/models.py` in the code editor, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 +``` + +> Double-check that you use two underscore characters (`_`) on each side of `str`. This convention is used frequently in Python and sometimes we also call them "dunder" (short for "double-underscore"). + +It looks scary, right? But don't worry – we will explain what these lines mean! + +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. + +`class Post(models.Model):` – this line defines our model (it is an `object`). + +- `class` is a special keyword that indicates that we are defining an object. +- `Post` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `models.Model` means that the Post is a Django Model, so Django knows that it should be saved in the database. + +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) + +- `models.CharField` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. + +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types). + +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. + +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. + +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. + +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! + +### Create tables for models in your database + +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. + +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/fi-FI/django_orm/README.md b/fi-FI/django_orm/README.md new file mode 100644 index 00000000000..7fdc215a875 --- /dev/null +++ b/fi-FI/django_orm/README.md @@ -0,0 +1,221 @@ +# Django ORM and QuerySets + +In this chapter you'll learn how Django connects to the database and stores data in it. Let's dive in! + +## What is a QuerySet? + +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. + +It's easiest to learn by example. Let's try this, shall we? + +## Django shell + +Open up your local console (not on PythonAnywhere) and type this command: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +The effect should be like this: + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too. + +### Kaikki objektit + +Let's try to display all of our posts first. You can do that with the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? + +### Create object + +This is how you create a new Post object in database: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? + +Let's import User model first: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +What users do we have in our database? Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +This is the superuser we created earlier! Let's get an instance of the user now (adjust this line to use your own username): + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! + +Now we can finally create our post: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Hurray! Wanna check if it worked? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +There it is, one more post in the list! + +### Add more posts + +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. + +### Filter objects + +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. We will use `filter` instead of `all` in `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Now our piece of code looks like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** There are two underscore characters (`_`) between `title` and `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +And then publish it with our `publish` method: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Ordering objects + +QuerySets also allow you to order the list of objects. Let's try to order them by `created_date` field: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +We can also reverse the ordering by adding `-` at the beginning: + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Complex queries through method-chaining + +As you saw, some methods on `Post.objects` return a QuerySet. The same methods can in turn also be called on a QuerySet, and will then return a new QuerySet. Thus, you can combine their effect by **chaining** them together: + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +This is really powerful and lets you write quite complex queries. + +Cool! You're now ready for the next part! To close the shell, type this: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/fi-FI/django_start_project/README.md b/fi-FI/django_start_project/README.md new file mode 100644 index 00000000000..3767c62e17f --- /dev/null +++ b/fi-FI/django_start_project/README.md @@ -0,0 +1,260 @@ +# Your first Django project! + +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. The django-marcador tutorial is copyrighted by Markus Zapke-Gründemann et al. + +We're going to create a small blog! + +The first step is to start a new Django project. Basically, this means that we'll run some scripts provided by Django that will create the skeleton of a Django project for us. This is just a bunch of directories and files that we will use later. + +The names of some files and directories are very important for Django. You should not rename the files that we are about to create. Moving them to a different place is also not a good idea. Django needs to maintain a certain structure to be able to find important things. + +> Remember to run everything in the virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. We explained how to do that in the **Django installation** chapter in the **Working with virtualenv** part. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. + + + +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + + + + + +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + + +`django-admin.py` is a script that will create the directories and files for you. You should now have a directory structure which looks like this: + + djangogirls + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. + +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. + +The `settings.py` file contains the configuration of your website. + +Remember when we talked about a mail carrier checking where to deliver a letter? `urls.py` file contains a list of patterns used by `urlresolver`. + +Let's ignore the other files for now as we won't change them. The only thing to remember is not to delete them by accident! + +## Changing settings + +Let's make some changes in `mysite/settings.py`. Open the file using the code editor you installed earlier. + +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +It would be nice to have the correct time on our website. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for English or `de` for German, and the country code, e.g. `de` for Germany or `ch` for Switzerland. If English is not your native language, you can add this to change the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +If you want a different language, change the language code by changing the following line: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.amazonaws.com` to the `ALLOWED_HOSTS` if you are using cloud9 +> +> If you are hosting your project on `Glitch.com`, let us protect the Django secret key that needs to remain confidential (otherwise, anyone remixing your project could see it): +> +> - First, we are going to create a random secret key. Open the Glitch terminal again, and type the following command: +> +> {% filename %}command-line{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> This should display a long random string, perfect to use as a secret key for your brand new Django web site. We will now paste this key into a `.env` file that Glitch will only show you if you are the owner of the web site. +> +> - Create a file `.env` at the root of your project and add the following property in it: +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Here, inside the single quotes, you can cut and paste the random key generated above +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Then update the Django settings file to inject this secret value and set the Django web site name: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - And a little further down in the same file, we inject the name of your new Glitch website: +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> The `PROJECT_DOMAIN` value is automatically generated by Glitch. It will correspond to the name of your project. + +## Set up a database + +There's a lot of different database software that can store data for your site. We'll use the default one, `sqlite3`. + +This is already set up in this part of your `mysite/settings.py` file: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +To create a database for our blog, let's run the following in the console: `python manage.py migrate` (we need to be in the `djangogirls` directory that contains the `manage.py` file). If that goes well, you should see something like this: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +And we're done! Time to start the web server and see if our website is working! + +## Starting the web server + +You need to be in the directory that contains the `manage.py` file (the `djangogirls` directory). In the console, we can start the web server by running `python manage.py runserver`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +or this one if you are using Glitch: + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +If you are on Windows and this fails with `UnicodeDecodeError`, use this command instead: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Now you need to check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: + +{% filename %}browser{% endfilename %} + + http://127.0.0.1:8000/ + + +If you're using a Chromebook and Cloud9, instead click the URL in the pop-up window that should have appeared in the upper right corner of the command window where the web server is running. The URL will look something like: + +{% filename %}browser{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +or on Glitch: + + https://name-of-your-glitch-project.glitch.me + + +Congratulations! You've just created your first website and run it using a web server! Isn't that awesome? + +![Install worked!](images/install_worked.png) + +Note that a command window can only run one thing at a time, and the command window you opened earlier is running the web server. As long as the web server is running and waiting for additional incoming requests, the terminal will accept new text but will not execute new commands. + +> We reviewed how web servers work in the **How the Internet works** chapter. + +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv -- to review instructions on how to open a second terminal window, see [Introduction to the command line](../intro_to_command_line/README.md). To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). + +Ready for the next step? It's time to create some content! \ No newline at end of file diff --git a/fi-FI/django_templates/README.md b/fi-FI/django_templates/README.md new file mode 100644 index 00000000000..167eb84ba04 --- /dev/null +++ b/fi-FI/django_templates/README.md @@ -0,0 +1,108 @@ +# Django mallit + +Time to display some data! Django gives us some helpful built-in **template tags** for that. + +## What are template tags? + +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. + +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! + +## Display post list template + +In the previous chapter we gave our template a list of posts in the `posts` variable. Now we will display it in HTML. + +To print a variable in Django templates, we use double curly brackets with the variable's name inside, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Try this in your `blog/templates/blog/post_list.html` template. Open it up in the code editor, and replace everything from the second `
` to the third `
` with `{{ posts }}`. Save the file, and refresh the page to see the results: + +![Kuva 13.1](images/step1.png) + +As you can see, all we've got is this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +This means that Django understands it as a list of objects. Remember from **Introduction to Python** how we can display lists? Yes, with for loops! In a Django template you do them like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Try this in your template. + +![Kuva 13.2](images/step2.png) + +It works! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. You can mix HTML and template tags. Our `body` will look like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Everything you put between `{% for %}` and `{% endfor %}` will be repeated for each object in the list. Refresh your page:{% endraw %} + +![Kuva 13.3](images/step3.png) + +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }}`)? We are accessing data in each of the fields defined in our `Post` model. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. + +## One more thing + +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… + +* First, push your code to GitHub + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Then, log back in to [PythonAnywhere](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one), and run: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +* Finally, hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. (To reach other PythonAnywhere pages from the console, use the menu button in the upper right corner.) Your update should be live on https://subdomain.pythonanywhere.com -- check it out in the browser! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. + +Congrats! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://subdomain.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. + +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/fi-FI/django_urls/README.md b/fi-FI/django_urls/README.md new file mode 100644 index 00000000000..9bf28746a77 --- /dev/null +++ b/fi-FI/django_urls/README.md @@ -0,0 +1,103 @@ +# Django URLs + +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. + +## What is a URL? + +A URL is a web address. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Kyllä! `127.0.0.1:8000` is a URL! And `https://djangogirls.org` is also a URL.) + +![URL](images/url.png) + +Every page on the Internet needs its own URL. This way your application knows what it should show to a user who opens that URL. In Django, we use something called `URLconf` (URL configuration). URLconf is a set of patterns that Django will try to match the requested URL to find the correct view. + +## How do URLs work in Django? + +Let's open up the `mysite/urls.py` file in your code editor of choice and see what it looks like: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. + +The admin URL, which you visited in the previous chapter, is already here: + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case, we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. + +## Your first Django URL! + +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of posts. + +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. + +Go ahead, add a line that will import `blog.urls`. You will also need to change the `from django.urls…` line because we are using the `include` function here, so you will need to add that import to the line. + +Your `mysite/urls.py` file should now look like this: + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('blog.urls')), +] +``` + +Django will now redirect everything that comes into 'http://127.0.0.1:8000/' to `blog.urls` and looks for further instructions there. + +## blog.urls + +Create a new empty file named `urls.py` in the `blog` directory, and open it in the code editor. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Here we're importing Django's function `path` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) + +After that, we can add our first URL pattern: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +As you can see, we're now assigning a `view` called `post_list` to the root URL. This URL pattern will match an empty string and the Django URL resolver will ignore the domain name (i.e., http://127.0.0.1:8000/) that prefixes the full URL path. This pattern will tell Django that `views.post_list` is the right place to go if someone enters your website at the 'http://127.0.0.1:8000/' address. + +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. This can be the same as the name of the view but it can also be something completely different. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. + +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. + +![Virhe](images/error1.png) + +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage, your `/admin/` will also not work. No worries – we will get there. If you see a different error message, try restarting your web server. To do that, in the console window that is running the web server, stop it by pressing Ctrl+C (the Control and C keys together). On Windows, you might have to press Ctrl+Break. Then you need to restart the web server by running a `python manage.py runserver` command. + +> If you want to know more about Django URLconfs, look at the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/ \ No newline at end of file diff --git a/fi-FI/django_views/README.md b/fi-FI/django_views/README.md new file mode 100644 index 00000000000..618b82f77e0 --- /dev/null +++ b/fi-FI/django_views/README.md @@ -0,0 +1,44 @@ +# Django views – time to create! + +Time to get rid of the bug we created in the last chapter! :) + +A *view* is a place where we put the "logic" of our application. It will request information from the `model` you created before and pass it to a `template`. We'll create a template in the next chapter. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. + +Views are placed in the `views.py` file. We will add our *views* to the `blog/views.py` file. + +## blog/views.py + +OK, let's open up this file in our code editor and see what's in there: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. + +Let's create a *view* as the comment suggests. Add the following minimal view below it: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +As you can see, we created a function (`def`) called `post_list` that takes `request` and will `return` the value it gets from calling another function `render` that will render (put together) our template `blog/post_list.html`. + +Save the file, go to http://127.0.0.1:8000/ and see what we've got. + +Another error! Read what's going on now: + +![Virhe](images/error.png) + +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! + +> Learn more about Django views by reading the official documentation: https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/fi-FI/dynamic_data_in_templates/README.md b/fi-FI/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..5a6ef017adf --- /dev/null +++ b/fi-FI/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# Dynamic data in templates + +We have different pieces in place: the `Post` model is defined in `models.py`, we have `post_list` in `views.py` and the template added. But how will we actually make our posts appear in our HTML template? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? + +This is exactly what *views* are supposed to do: connect models and templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. + +OK, so how will we achieve this? + +We need to open our `blog/views.py` in our code editor. So far `post_list` *view* looks like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Remember when we talked about including code written in different files? Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Then we import the name of the model (`Post`). + +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. + +## QuerySet + +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +So, let's open the `blog/views.py` file in the code editor, and add this piece of code to the function `def post_list(request)` -- but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +To display our QuerySet on our blog's post list, we have two things left to do: + +1. Pass the `posts` QuerySet to the template context, by changing the `render` function call. We'll do this now. +2. Modify the template to display the `posts` QuerySet. We'll cover this in a later chapter. + +Please note that we create a *variable* for our QuerySet: `posts`. Treat this as the name of our QuerySet. From now on we can refer to it by this name. + +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. We need to give them names (we will stick to `'posts'` right now). :) It should look like this: `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. + +So finally our `blog/views.py` file should look like this: + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +That's it! Time to go back to our template and display this QuerySet! + +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/fi-FI/extend_your_application/README.md b/fi-FI/extend_your_application/README.md new file mode 100644 index 00000000000..874265f1a51 --- /dev/null +++ b/fi-FI/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Extend your application + +We've already completed all the different steps necessary for the creation of our website: we know how to write a model, URL, view and template. We also know how to make our website pretty. + +Time to practice! + +The first thing we need in our blog is, obviously, a page to display one post, right? + +We already have a `Post` model, so we don't need to add anything to `models.py`. + +## Create a template link to a post's detail + +We will start with adding a link inside `blog/templates/blog/post_list.html` file. Open it in the code editor, and so far it should look like this: {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% raw %}We want to have a link from a post's title in the post list to the post's detail page. Let's change `

{{ post.title }}

` so that it links to the post's detail page:{% endraw %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% raw %}Time to explain the mysterious `{% url 'post_detail' pk=post.pk %}`. As you might suspect, the `{% %}` notation means that we are using Django template tags. This time we will use one that will create a URL for us!{% endraw %} + +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail + +And how about `pk=post.pk`? `pk` is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk". Because we didn't specify a primary key in our `Post` model, Django creates one for us (by default, a field named "id" holding a number that increases for each record, i.e. 1, 2, 3) and adds it as a field to each of our posts. We access the primary key by writing `post.pk`, the same way we access other fields (`title`, `author`, etc.) in our `Post` object! + +Now when we go to http://127.0.0.1:8000/ we will have an error (as expected, since we do not yet have a URL or a *view* for `post_detail`). It will look like this: + +![NoReverseMatch error](images/no_reverse_match2.png) + +## Create a URL to a post's detail + +Let's create a URL in `urls.py` for our `post_detail` *view*! + +We want our first post's detail to be displayed at this **URL**: http://127.0.0.1:8000/post/1/ + +Let's make a URL in the `blog/urls.py` file to point Django to a *view* named `post_detail`, that will show an entire blog post. Open the `blog/urls.py` file in the code editor, and add the line `path('post//', views.post_detail, name='post_detail'),` so that the file looks like this: + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +This part `post//` specifies a URL pattern – we will explain it for you: + +- `post/` means that the URL should begin with the word **post** followed by a **/**. So far so good. +- `` – this part is trickier. It means that Django expects an integer value and will transfer it to a view as a variable called `pk`. +- `/` – then we need a **/** again before finishing the URL. + +That means if you enter `http://127.0.0.1:8000/post/5/` into your browser, Django will understand that you are looking for a *view* called `post_detail` and transfer the information that `pk` equals `5` to that *view*. + +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! + +![AttributeError](images/attribute_error2.png) + +Do you remember what the next step is? It's adding a view! + +## Add a post's detail view + +This time our *view* is given an extra parameter, `pk`. Our *view* needs to catch it, right? So we will define our function as `def post_detail(request, pk):`. Note that this parameter must have the exact same name as the one we specified in `urls` (`pk`). Also note that omitting this variable is incorrect and will result in an error! + +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```python +Post.objects.get(pk=pk) +``` + +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! + +![DoesNotExist error](images/does_not_exist2.png) + +We don't want that! But luckily Django comes with something that will handle that for us: `get_object_or_404`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. + +![Sivua ei löydy](images/404_2.png) + +The good news is that you can actually create your own `Page not found` page and make it as pretty as you want. But it's not super important right now, so we will skip it. + +OK, time to add a *view* to our `views.py` file! + +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. + +We should open `blog/views.py` in the code editor and add the following code near the other `from` lines: + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Yes. It is time to refresh the page: http://127.0.0.1:8000/ + +![Post list view](images/post_list2.png) + +It worked! But what happens when you click a link in blog post title? + +![TemplateDoesNotExist error](images/template_does_not_exist2.png) + +Oh no! Another error! But we already know how to deal with it, right? We need to add a template! + +## Create a template for the post details + +We will create a file in `blog/templates/blog` called `post_detail.html`, and open it in the code editor. + +Enter the following code: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ 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 %} + +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. + +![Post detail page](images/post_detail2.png) + +Yay! It works! + +# Deploy time! + +It'd be good to see if your website still works on PythonAnywhere, right? Let's try deploying again. + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ 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/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(Remember to substitute `` with your actual PythonAnywhere subdomain, without the angle-brackets.) + +## Updating the static files on the server + +Servers like PythonAnywhere like to treat "static files" (like CSS files) differently from Python files, because they can optimise for them to be loaded faster. As a result, whenever we make changes to our CSS files, we need to run an extra command on the server to tell it to update them. The command is called `collectstatic`. + +Start by activating your virtualenv if it's not still active from earlier (PythonAnywhere uses a command called `workon` to do this, it's just like the `source myenv/bin/activate` command you use on your own computer): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +The `manage.py collectstatic` command is a bit like `manage.py migrate`. We make some changes to our code, and then we tell Django to *apply* those changes, either to the server's collection of static files, or to the database. + +In any case, we're now ready to hop on over to the ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (from the menu button in the upper right of the console) and hit **Reload**, and then look at the https://subdomain.pythonanywhere.com page to see the result. + +And that should be it. Congrats! :) \ No newline at end of file diff --git a/fi-FI/how_the_internet_works/README.md b/fi-FI/how_the_internet_works/README.md new file mode 100644 index 00000000000..af0cb24aee6 --- /dev/null +++ b/fi-FI/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# How the Internet works + +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> 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 consists of 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. + +If you're not familiar with programming, it can be hard to grasp HTML at first, but your web browsers (like Chrome, Safari, Firefox, etc.) love it. Web browsers are designed to understand this code, 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. + +OK, but you want to know how the Internet looks, right? + +We drew you a picture! It looks like this: + +![Kuva 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: + +![Kuva 1.2](images/internet_3.png) + +It is fascinating, isn't it? But 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: + +![Kuva 1.3](images/internet_2.png) + +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. + +![Kuva 1.4](images/internet_4.png) + +That's how it works - you send messages and you expect some response. 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 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, 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 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! \ No newline at end of file diff --git a/fi-FI/html/README.md b/fi-FI/html/README.md new file mode 100644 index 00000000000..6bf61ade0d9 --- /dev/null +++ b/fi-FI/html/README.md @@ -0,0 +1,227 @@ +# Introduction to HTML + +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 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 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**. + +## Your first template! + +Creating a template means creating a template file. Everything is a file, right? You have probably noticed this already. + +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 + + +(You might wonder why we need two directories both called `blog` – as you will discover later, this is 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 `TemplateDoesNotExist`, try to restart your server. Go to the command line, stop the server by pressing Ctrl+C (Control and C keys together) and start it again by running a `python manage.py runserver` command. + +![Kuva 11.1](images/step1.png) + +No error anymore! Congratulations! :) However, your website isn't actually publishing anything except an empty page, because your template is empty too. We need to fix that. + +Open the new file in the code editor, and add the following: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Hi there!

+

It works!

+ + +``` + +So how does your website look now? Visit it to find out: http://127.0.0.1:8000/ + +![Kuva 11.2](images/step3.png) + +It worked. Nice work there! :) + +* The line `` is not a HTML tag. It only declares the document type. Here, it informs the browser that document type is [HTML5](https://html.spec.whatwg.org/#the-doctype). This is always the beginning of any HTML5 file. +* The most basic tag, ``, is always the beginning of html content 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 and body + +Each HTML page is also divided into two elements: **head** and **body**. + +* **head** is an element that contains information about the document that is not displayed on the screen. + +* **body** is an element that contains everything else that is displayed as part of the web page. + +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 web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Save the file and refresh your page. + +![Kuva 11.3](images/step4.png) + +Notice how the browser has understood that "Ola's blog" is the title of your page? It has interpreted `Ola's blog` and placed the text in the title bar of your browser (it will also be used for bookmarks and so on). + +Probably you have also noticed that each opening tag is matched by a *closing tag*, with a `/`, and that elements are *nested* (i.e. you can't close a particular tag until all the ones that were inside it have been closed too). + +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. + +## 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 sub-heading

` for a heading at the next level +* `

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 and there's no closing tag) +* `link` creates a link +* `
  • first item
  • second item
` makes a list, just like this one! +* `
` defines a section of the page +* `` defines a set of navigation links +* `
` specifies independent, self-contained content +* `
` defines a section in a document +* `
` specifies a header for a document or section +* `
` specifies the main content of a document +* `` defines some content aside from the content it is placed in (like a sidebar) +* `
` defines a footer for a document or section +* `` defines a specific time (or datetime) + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Django Girls blog + + +
+

Django Girls Blog

+
+ +
+ +

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.

+
+ +
+ +

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.

+
+ + +``` + +We've created one `header` section and two `article` section here. + +* The `header` element contains the title of our blog – it's a heading and a link +* The two `article` elements contain our blog posts with a published date in a `time` element, a `h2` element with a post title that is clickable and a `p` (paragraph) element for text of our blog post. + +It gives us this effect: + +![Kuva 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**. + +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! + +It'd be good to see all this out and live on the Internet, right? Let's do another PythonAnywhere deploy: + +### Commit, and push your code up to GitHub + +First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): + +{% filename %}command-line{% endfilename %} + + $ git status + + +Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes in this directory: + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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): + +{% 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. + +{% 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: + +{% 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 %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +You'll need to substitute `` with your actual PythonAnywhere subdomain name, without the angle-brackets. Your subdomain name is normally your PythonAnywhere user name, but in some cases it might be a bit different (such as if your user name contains capital letters). So if this command doesn't work, use the `ls` (list files) command to find your actual subdomain/folder name, and then `cd` to there. + +Now watch your code get downloaded. If you want to check that it's arrived, you can hop over to the **"Files" page** and view your code on PythonAnywhere (you can reach other PythonAnywhere pages from the menu button on the console page). + +* Finally, hop on over to the ["Web" page](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. :) \ No newline at end of file diff --git a/fi-FI/installation/README.md b/fi-FI/installation/README.md new file mode 100644 index 00000000000..442f416b5f2 --- /dev/null +++ b/fi-FI/installation/README.md @@ -0,0 +1,68 @@ +# 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 installing things as they are needed in the tutorial -- this is just an additional page that gathers all of the installation instructions in one place (which is useful for some workshop formats). You can choose to install everything that is on this page right now if you wish. 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 parts to you later on, as they are needed. + +Good luck! + +# If you're attending a workshop + +If you are attending one of the [Django Girls events](https://djangogirls.org/events/): + +* Your workshop may have an "installation party" before the main workshop. If you are at an installation party, this page is for you! Follow the instructions here to get everything you need for the workshop installed, with the help of the coaches if needed. Then at the main workshop, you'll be able to skip installation instructions you'll encounter in the main tutorial when you get to them. +* The organizers of your workshop may have asked you to try at home to install everything on your computer before the workshop starts. If you have been asked to do that, this page is for you! Follow the instructions here, as best you can. Then at the main workshop, when you get to an installation step in the main tutorial, if you were not able to get that piece installed you can get help from your coach. +* If your workshop does not have an installation party (or you couldn't attend), and if the organizers didn't ask you to try to install everything before you arrived, skip this page and go straight to the [How the Internet works](../how_the_internet_works/README.md) chapter. You'll be installing everything you need as you work through the tutorial. + +# Asennus + +In this tutorial you will be building a blog. In order to do that, as you go through the tutorial you'll be instructed on how to install various software on your computer and set up some online accounts as they are needed. This page gathers all of the installation and sign-up instructions in one place (which is useful for some workshop formats). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brief intro to the command line {#command-line} + +Many of the steps below reference the "console", "terminal", "command window", or "command line" -- these all mean the same thing: a window on your computer where you can enter commands. When you get to the main tutorial, you'll learn more about the command line. For now, the main thing you need to know is how to open a command window and what it looks like: {% include "/intro_to_command_line/open_instructions.md" %} + +# Install Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Install a code editor {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Set up virtualenv and install Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Install Git {#git} + +{% include "/deploy/install_git.md" %} + +# Create a GitHub account {#github-account} + +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. Be sure to remember your password (add it to your password manager, if you use one). + +# Create a PythonAnywhere account {#pythonanywhere-account} + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Aloita lukeminen + +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) + +* [Mikä on 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. \ No newline at end of file diff --git a/fi-FI/intro_to_command_line/README.md b/fi-FI/intro_to_command_line/README.md new file mode 100644 index 00000000000..142f4eba7ae --- /dev/null +++ b/fi-FI/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction to the command-line interface + +> 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' 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. 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. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## 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 a `$`, like this: + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +On Windows, you probably see a `>`, like this: + +{% filename %}command-line{% endfilename %} + + > + + +Take a look at the Linux section just above now -- you'll see something more like that when you get to PythonAnywhere later in the tutorial. + + + +Each command will be prepended by a `$` or `>` and one space, but you should not 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 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. Ignore the left part and only type in the command, which starts after the prompt. + +## Your first command (YAY!) + +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +And then hit `enter`. This is our result: + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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! + +## Basics + +Each operating system has a slightly different set of commands for the command line, so make sure to follow instructions for your operating system. Let's try this, shall we? + +### Current directory + +It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Note: 'pwd' stands for 'print working directory'. + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note: 'cd' stands for 'change directory'. With PowerShell you can use pwd just like on Linux or Mac OS X. + + + +You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. + +* * * + +### Learn more about a command + +Many commands you can type at the command prompt have built-in help that you can display and read! For example, to learn more about the current directory command: + + + +OS X and Linux have a `man` command, which gives you help on commands. Try `man pwd` and see what it says, or put `man` before other commands to see their help. The output of `man` is normally paged. Use the space bar to move to the next page, and `q` to quit looking at the help. + + + + + +Adding a `/?` suffix to most commands will print the help page. You may need to scroll your command window up to see it all. Try `cd /?`. + + + +### List files and directories + +So what's in it? It'd be cool to find out. Let's see: + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Desktop + Downloads + Music + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM
Applications + 05/08/2020 07:28 PM Desktop + 05/08/2020 07:28 PM Downloads + 05/08/2020 07:28 PM Music + ... + + +> Note: In PowerShell you can also use 'ls' like on Linux and Mac OS X. + +* * * + +### Change current directory + +Now, let's go to our Desktop directory: + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Desktop + + +Note that the directory name "Desktop" might be translated to the language of your Linux account. If that's the case, you'll need to replace `Desktop` with the translated name; for example, `Schreibtisch` for German. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Desktop + + + + +Check if it's really changed: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /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 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` key twice to get a list of options. + +* * * + +### Luo hakemisto + +How about creating a practice directory on your desktop? You can do it this way: + + + +{% filename %}command-line{% endfilename %} + + $ mkdir practice + + + + + + +{% 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 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. + +* * * + +### Exercise! + +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) + +#### Solution: + + + +{% filename %}command-line{% endfilename %} + + $ cd practice + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd practice + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Congrats! :) + +* * * + +### Clean up + +We don't want to leave a mess, so let's remove everything we did until that point. + +First, we need to get back to Desktop: + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% 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: + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Desktop + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Desktop + + + + +Now time to delete the `practice` directory: + +> **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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r practice + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S practice + practice, Are you sure ? Y + + + + +Done! To be sure it's actually deleted, let's check it: + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### Poistu + +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 + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, huh? :) + +## Yhteenveto + +Here is a summary of some useful commands: + +| Command (Windows) | Command (Mac OS / Linux) | Kuvaus | Esimerkki | +| ----------------- | ------------------------ | -------------------------- | -------------------------------------------------- | +| poistu | poistu | sulje ikkuna | **poistu** | +| cd | cd | change directory | **cd test** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | +| dir | ls | list directories/files | **dir** | +| copy | cp | kopioi tiedosto | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | siirrä tiedosto | **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** | +| [CMD] /? | man [CMD] | get help for a command | **cd /?** (Windows) or **man cd** (Mac OS / Linux) | + +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. + +If you're curious, [ss64.com](http://ss64.com) contains a complete reference of commands for all operating systems. + +## Valmis? + +Let's dive into Python! \ No newline at end of file diff --git a/fi-FI/intro_to_command_line/open_instructions.md b/fi-FI/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..c4d21aa67e4 --- /dev/null +++ b/fi-FI/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Depending on your version of Windows and your keyboard, one of the following should open a command window (you may have to experiment a bit, but you don't have to try all of these suggestions): + +- Go to the Start menu or screen, and enter "Command Prompt" in the search field. +- Go to Start menu → Windows System → Command Prompt. +- Go to Start menu → All Programs → Accessories → Command Prompt. +- Go to the Start screen, hover your mouse in the lower-left corner of the screen, and click the down arrow that appears (on a touch screen, instead flick up from the bottom of the screen). The Apps page should open. Click on Command Prompt in the Windows System section. +- Hold the special Windows key on your keyboard and press the "X" key. Choose "Command Prompt" from the pop-up menu. +- Hold the Windows key and press the "R" key to get a "Run" window. Type "cmd" in the box, and click the OK key. + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Later in this tutorial, you will need to have two command windows open at the same time. However, on some versions of Windows, if you already have one command window open and you try to open a second one using the same method, it will instead point you to the command window you already have open. Try it now on your computer and see what happens! If you only get one command window, try one of the other methods in the list above. At least one of them should result in a new command window being opened. + + + + + +Go to Applications → Utilities → Terminal. + + + + + +It's probably under Applications → Accessories → Terminal, or Applications → System → Terminal, but that may depend on your system. If it's not there, you can try to Google it. :) + + \ No newline at end of file diff --git a/fi-FI/python_installation/README.md b/fi-FI/python_installation/README.md new file mode 100644 index 00000000000..8470b71f1f4 --- /dev/null +++ b/fi-FI/python_installation/README.md @@ -0,0 +1,15 @@ +# Let’s start with Python + +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 simpler than other programming languages, but don't worry – Python is also really powerful! + +# Python installation + +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the [installation steps](../installation/README.md), there's no need to do this again – you can skip straight ahead to the next chapter! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/fi-FI/python_installation/instructions.md b/fi-FI/python_installation/instructions.md new file mode 100644 index 00000000000..592aafe0b5d --- /dev/null +++ b/fi-FI/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 the latest version of Python 3, so if you have any earlier version, you will need to upgrade it. If you already have version {{ book.py_min_version }} or higher you should be fine. + +Please install normal Python as follows, even when you have Anaconda installed on your computer. + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, on the "System type" line of the System Info page. To reach this page, try one of these methods: + +* Press the Windows key and Pause/Break key at the same time +* Open your Control Panel from the Windows menu, then navigate to System & Security, then System +* Press the Windows button, then navigate to Settings > System > About +* Search the Windows Start menu for "System Information". To do that, click the Start button or press the Windows key, then begin to type `System Information`. It will start making suggestions as soon as you type. You can select the entry once it shows up. + +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 {{ book.py_version }} to PATH" or 'Add Python to your environment variables" checkbox and click on "Install Now", as shown here (it may look a bit different if you are installing a different version): + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +When the installation completes, you may see a dialog box with a link you can follow to learn more about Python or about the version you installed. Close or cancel that dialog -- you'll be learning more in this tutorial! + +Note: If you are using an older version of Windows (7, Vista, or any older version) and the Python {{ book.py_version }} installer fails with an error, then install all Windows Updates and try to install Python again. If you still have the error, try installing Python version {{ book.py_min_release }} from [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} needs Python {{ book.py_min_version }} or greater, which does not support Windows XP or earlier versions. + + + + + +> **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/mac-osx/ and download the latest Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-{{ book.py_release }}-macosx10.9.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 {{ book.py_release }} + + +If you have a different version of Python installed, at least {{ book.py_min_version }} (e.g. {{ book.py_min_release }}), then you don't have to upgrade. If you don't have Python installed, or if you want a different version, first check what Linux distribution you are using with the following command: + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Afterwards, depending on the result, follow one of the following installation guides below this section. + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} + + $ sudo apt install python3 + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo dnf install python3 + + +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use `yum` instead. + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} + + $ sudo zypper install python3 + + + + +Verify the installation was successful by opening a command prompt and running the `python3` command: + +{% filename %}command-line{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +The version shown may be different from {{ book.py_release }} -- it should match the version you installed. + +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python that is {{ book.py_min_version }} or higher. If that doesn't work either, you may open a new command prompt and try again; this happens if you use a command prompt left open from before the Python installation. + +* * * + +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. \ No newline at end of file diff --git a/fi-FI/python_introduction/README.md b/fi-FI/python_introduction/README.md new file mode 100644 index 00000000000..171e8729ef8 --- /dev/null +++ b/fi-FI/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introduction to Python + +> 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 + +> 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`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + 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. + +If you want to exit the Python console at any point, type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. + +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. + +{% 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` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +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: + +{% 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 (there is no difference!) The quotes tell Python that what's inside of them is a string. + +Strings can be strung together. Try this: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` + +You can also multiply strings with a number: + +{% 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +or escaping the apostrophe with a backslash (``): + +{% filename %}command-line{% endfilename %} + +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Nice, huh? To see your name in uppercase letters, type: + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +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! + +{% 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. + +### Yhteenveto + +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. + +These are the basics of every programming language you learn. Ready for something harder? We bet you are! + +## Virheet + +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`: + +{% filename %}{{ warning_icon }} 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! The {{ warning_icon }} icon is our way of giving you a heads up that the code you are about to run won't work as expected. Making mistakes (even intentional ones) are an important part of learning! + +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? + +{% 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? + +## Muuttujat + +An important concept in programming is variables. A variable is nothing more than a name for something so you can use it later. Programmers use these variables to store data, make their code more readable and so they don't have to keep remembering what things are. + +Let's say we want to create a new variable called `name`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +We type 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? Enter `name` and hit `enter`: + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +You can use it in functions too: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Awesome, right? Now, variables can be anything – numbers too! Try this: + +{% 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! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +Virhe! 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. + +Play with this for a while and see what you can do! + +## The print function + +Try this: + +{% 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. + +As we'll see later, `print()` is also useful when we want to print things from inside functions, or when we want to print things on multiple lines. + +## 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. :) + +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: + +{% 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! + +{% 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: + +{% 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: + +{% 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! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +If you want to add something to your list, you can do this by typing this command: + +{% 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: + +{% 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 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. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +That worked like a charm! + +For extra fun, try some other indexes: 6, 7, 1000, -1, -6 or -1000. See if you can predict the result before trying the command. Do the results make sense? + +You can find a list of all available list methods in this chapter of the Python documentation: https://docs.python.org/3/tutorial/datastructures.html + +## Sanakirjat + +> 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 substituting your own information, too): + +{% 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: + +- The key `name` points to the value `'Ola'` (a `string` object), +- `country` points to `'Poland'` (another `string`), +- and `favorite_numbers` points to `[7, 42, 92]` (a `list` with three numbers in it). + +You can check the content of individual keys with this syntax: + +{% 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. + +What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! + +{% filename %}{{ warning_icon }} 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 should you use a dictionary or a list? Well, that's a good point to ponder. Think about the answer before looking at it 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 a dictionary after it is created, like this: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Like lists, using the `len()` function on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, type in the following command: + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> 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 well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% 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 learned another amazing thing. + +### Yhteenveto + +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 + +Excited for the next part? :) + +## Compare things + +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers! Let's see how that works: + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare values of mathematical expressions like `2 * 2` and function results like the `2` returned by `len([4, 5])`. 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 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: + +{% filename %}command-line{% endfilename %} + +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: + +- x `>` y means: x is greater than y +- x `<` y means: x is less than y +- x `<=` y means: x is less than or equal to y +- x `>=` y means: x is greater than or equal to y + +Awesome! Wanna do one more? Try this: + +{% 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 + +Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and '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 **Boolean**. + +There are only two Boolean objects: + +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well.) + +Booleans can be variables, too! See here: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +You can also do it this way: + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Practice and have fun with Booleans by trying to run the following commands: + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +Congrats! Booleans are one of the coolest features in programming, and you just learned how to use them! + +# Save it! + +> 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, type the `exit()` function + +{% 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 (or if you're using a Chromebook, create a new file in the cloud IDE and open the file, which will be in the included code editor): + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +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. + +> **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. :) + +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. + + + +On a Mac, the command will look something like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +On Linux, it will be like this: + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(Remember that the word "Desktop" might be translated to your local language.) + + + + + +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +If you get stuck, ask for help. That's exactly what the coaches are here for! + +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: + +{% 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? + +You can now move on to an essential tool in programming: + +## If … elif … else + +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 were to save and run this, we'd see an error like this: + +{% filename %}{{ warning_icon }} 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!') +``` + +Notice how we've indented the next line of code by 4 spaces? We need to do this so Python knows what code to run if the result is true. You can do one space, but nearly all Python programmers do 4 to make things look neat. A single Tab will also count as 4 spaces as long as your text editor is set to do so. When you made your choice, don't change it! If you already indented with 4 spaces, make any future indentation with 4 spaces, too - otherwise you may run into problems. + +Save it and give it another run: + +{% 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 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') +else: + print('5 is not greater than 2') +``` + +When this is run it will print out: + +{% 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. Let's see how `elif` works: + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +and executed: + +{% 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 + + +## Kommentit + +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. + +### Yhteenveto + +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. +- **comments** - lines that Python won't run which let you document your code + +Time for the last part of this chapter! + +## Your own functions! + +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +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 give it a go. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + +Okay, our first function is ready! + +You may wonder why we've written the name of the function at the bottom of the file. When we write `def hi():` and the indented lines following, this is us writing instructions for what the `hi()` function should do. Python will read and remember these instructions, but won't run the function yet. To tell Python we want to run the function, we have to call the function with `hi()`. Python reads the file and executes it from top to bottom, so we have to define the function in the file before we call it. + +Let's run this now and see what happens: + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: + +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. + +Let's build our first function with parameters. We will change 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': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +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: + +{% filename %}{{ warning_icon }} 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: + +{% 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: + +{% 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: + +{% filename %}command-line{% endfilename %} + + Hei Anonyymi! + + +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? Replace the content of your file with the following: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Let's call the code now: + +{% 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: +``` + +The `for` statement behaves similarly to the `if` statement; code below both of these need to be indented four spaces. + +Here is the full code that will be in the file: + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +And when we run it: + +{% 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: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Which would print: + +{% 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 by that we mean it includes the first value, but not the last. + +## Yhteenveto + +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! + +For official and full python tutorial visit https://docs.python.org/3/tutorial/. This will give you a more thorough and complete study of the language. Cheers! :) + +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) \ No newline at end of file diff --git a/fi-FI/template_extending/README.md b/fi-FI/template_extending/README.md new file mode 100644 index 00000000000..c1052de8b78 --- /dev/null +++ b/fi-FI/template_extending/README.md @@ -0,0 +1,151 @@ +# Template extending + +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. + +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 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 + + +Then open it up in the code editor and copy everything from `post_list.html` to `base.html` file, like this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Then in `base.html`, replace your whole `` (everything between `` and ``) with this: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}You might notice this replaced everything from `{% for post in posts %}` to `{% endfor %}` with: {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +Mutta miksi? You just created a `block`! You used the template tag `{% block %}` to make an area that will have HTML inserted in it. That HTML will come from another template that extends this template (`base.html`). We will show you how to do this in a moment. + +Now save `base.html` and open your `blog/templates/blog/post_list.html` again in the code editor. {% raw %}You're going to remove everything above `{% for post in posts %}` and below `{% endfor %}`. When you're done, the file will look like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +We want to use this as part of our template for all the content blocks. Time to add block tags to this file! + +{% 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 %}`. Like this:{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ 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' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +That's it! Save the file, and check if your website is still working properly. :) + +> 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. \ No newline at end of file diff --git a/fi-FI/whats_next/README.md b/fi-FI/whats_next/README.md new file mode 100644 index 00000000000..bbcd36fd21e --- /dev/null +++ b/fi-FI/whats_next/README.md @@ -0,0 +1,43 @@ +# Mitä seuraavaksi? + +Congratulate yourself! **You're totally awesome**. We're proud! <3 + +### What to do now? + +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](https://twitter.com/djangogirls) to stay up to date. + +### Can you recommend any further resources? + +Kyllä! There are a *lot* of resources online for learning all kinds of programming skills – it can be pretty daunting to work out where to go next, but we've got you covered. Whatever your interests were before you came to Django Girls, and whatever interests you've developed throughout the tutorial, here are some free resources (or resources with large free components) you can use to get to where you want to be. + +#### Django + +- Our other book, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Django's official tutorial](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Getting Started With Django video lessons](http://www.gettingstartedwithdjango.com/) +- [Django for Everybody Specialization](https://www.coursera.org/specializations/django) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses + +#### HTML, CSS and JavaScript + +- [Codecademy's web development course](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Codecademy's Python course](https://www.codecademy.com/learn/learn-python) +- [Google's Python course](https://developers.google.com/edu/python/) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) – the initial exercises are free +- [New Coder tutorials](http://newcoder.io/tutorials/) – this is a variety of practical examples of how you might use Python +- [edX](https://www.edx.org/course?search_query=python) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Coursera's Python specialization](https://www.coursera.org/specializations/python) – some video lectures can be audited for free and you can earn a Coursera Certificate by taking these courses +- [Python for Everybody](https://www.py4e.com/) - a free and open version of the Coursera Python for Everybody specialization + +#### Working with data + +- [Codecademy's data science course](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – you can audit most courses for free, but if you want a certificate or credits towards a higher education qualification then that will cost money +- [Dataquest](https://www.dataquest.io/) – the first 30 "missions" are free + +We can't wait to see what you build next! \ No newline at end of file diff --git a/fr-FR/GLOSSARY.md b/fr-FR/GLOSSARY.md new file mode 100644 index 00000000000..48cb7aaa0d3 --- /dev/null +++ b/fr-FR/GLOSSARY.md @@ -0,0 +1,3 @@ +# Éditeur de texte + +L'éditeur de texte est une application qui permet d'écrire et 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) \ No newline at end of file diff --git a/fr-FR/README.md b/fr-FR/README.md new file mode 100644 index 00000000000..5ba91076d15 --- /dev/null +++ b/fr-FR/README.md @@ -0,0 +1,51 @@ +# Tutoriel de Django Girls + +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) + +> Cette œuvre est mise à disposition selon les termes de la Licence Creative Commons Attribution — ShareAlike 4.0 International. Pour consulter une copie de cette licence, visitez https://creativecommons.org/licenses/by-sa/4.0/deed.fr + +## Bienvenue + +Bienvenue dans le tutoriel Django Girls ! Nous sommes heureux de vous voir ici. :) Dans ce tutoriel, nous allons vous emmener dans un voyage sous le capot des technologies web, en vous offrant un aperçu de tous les pièces et les morceaux qui doivent être assemblés pour que le web fonctionne tel que nous le connaissons. + +Comme avec toutes les choses inconnues, cela va être une aventure, mais pas de soucis, puisque vous avez déjà eu le courage d'arriver ici, vous allez y arriver. :) + +## Introduction + +Avez-vous déjà eu l'impression que le monde est de plus en plus rempli de technologies avec lesquelles vous n'êtes pas (encore) familière ? 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 de l'informatique est trop compliqué, ne serait-ce que pour savoir par où commencer ? + +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 vous transformera pas magiquement en programmeuse. Si vous voulez devenir bonne, cela 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 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 ? + +Une fois que vous aurez terminé le tutoriel, vous aurez une petite application web : votre propre blog. Nous allons vous montrer comment le mettre en ligne, ainsi votre travail sera visible par d'autres ! + +Ça devrait ressembler plus ou moins à ça : + +![Figure 0.1](images/application.png) + +> Si vous travaillez avec le tutoriel de votre côté et n'avez pas un coach qui vous aiderait en cas de problème, nous avons un système de discussion instantanée pour vous : [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). 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'ayez pas peur et allez poser vos questions ! + +OK, [commençons par le commencement…](./how_the_internet_works/README.md) + +## Suivre le tutoriel chez soi + +Il est formidable de participer à un atelier Django Girls, mais nous comprenons qu'il n'est pas toujours facile d'en trouver un. C'est pourquoi nous vous encourageons à essayer de suivre ce tutoriel chez vous. Pour les lectrices à la maison, nous sommes actuellement en train de préparer des vidéos afin qu'il vous soit plus facile de suivre le tutoriel de votre côté. C'est encore un travail en cours, mais la chaine YouTube [Le code convient aux filles](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) couvre de plus en plus de choses. + +Dans chaque chapitre couvert se trouve un lien pointant vers la vidéo correspondante. + +## À propos et contributions + +Ce tutoriel est maintenu par [DjangoGirls](https://djangogirls.org/). 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](https://github.com/DjangoGirls/tutorial/blob/master/README.md). + +## Vous voulez nous aider à traduire le tutoriel dans d'autres langues ? + +Actuellement, les traductions sont faites sur la plateforme crowdin.com : + +https://crowdin.com/project/django-girls-tutorial + +Si votre langue n'est pas listée sur [crowdin](https://crowdin.com/), merci [d'ouvrir un ticket](https://github.com/DjangoGirls/tutorial/issues/new) pour nous en informer afin que nous la rajoutions. \ No newline at end of file diff --git a/fr-FR/SUMMARY.md b/fr-FR/SUMMARY.md new file mode 100644 index 00000000000..e0cd7739510 --- /dev/null +++ b/fr-FR/SUMMARY.md @@ -0,0 +1,35 @@ +# Résumé + +* [Introduction](README.md) +* [Installation](installation/README.md) + * [Ligne de commande](installation/README.md#command-line) + * [Python](installation/README.md#python) + * [Éditeur de code](installation/README.md#code-editor) + * [Environnement virtuel](installation/README.md#virtualenv) + * [Django](installation/README.md#django) + * [Git](installation/README.md#git) + * [GitHub](installation/README.md#github-account) + * [PythonAnywhere](installation/README.md#pythonanywhere-account) +* [Installation (chromebook)](chromebook_setup/README.md) +* [Comment marche 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) +* [Qu'est-ce que Django ?](django/README.md) +* [Installation de Django](django_installation/README.md) +* [Votre premier projet Django !](django_start_project/README.md) +* [Les modèles dans Django](django_models/README.md) +* [Django admin](django_admin/README.md) +* [Déployer !](deploy/README.md) +* [Les URL de Django](django_urls/README.md) +* [Vues Django – c'est l'heure de créer !](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 – donnez du style](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) +* [Et maintenant ?](whats_next/README.md) \ No newline at end of file diff --git a/fr-FR/chromebook_setup/README.md b/fr-FR/chromebook_setup/README.md new file mode 100644 index 00000000000..98cda3e1c66 --- /dev/null +++ b/fr-FR/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Installation de Chromebook + +> **Note** Si vous avez déjà passé les [étapes d’installation](../installation/README.md), il n'est pas nécessaire de les répéter - vous pouvez vous rendre directement à [Introduction à Python](../python_introduction/README.md). + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/fr-FR/chromebook_setup/instructions.md b/fr-FR/chromebook_setup/instructions.md new file mode 100644 index 00000000000..62ef8ea2dc0 --- /dev/null +++ b/fr-FR/chromebook_setup/instructions.md @@ -0,0 +1,158 @@ +Vous pouvez [passer cette section](http://tutorial.djangogirls.org/en/installation/#install-python) si vous n'utilisez pas un Chromebook. Sinon, votre installation sera un peu différente. Vous pouvez ignorer le reste des instructions d'installation. + +### Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com) + +Cloud 9 est un outil qui vous propose un éditeur de code et un accès à un ordinateur, fonctionnant sur Internet, sur lequel vous pouvez installer, écrire et exécuter des logiciels. Pour la durée du tutoriel, Cloud IDE agira comme votre *machine locale*. Vous lancerez toujours des commandes dans un terminal exactement comme vos camarades sous macOS, Ubuntu ou Windows, mais votre terminal sera connecté à un ordinateur distant que Cloud IDE aura configuré pour vous. Voici les instructions pour Cloud IDE (PaizaCloud Cloud IDE, AWS Cloud9, Glitch.com). Vous pouvez choisir l'un des cloud IDE et suivre les instructions du cloud IDE. + +#### PaizaCloud Cloud IDE + +1. Allez sur [PaizaCloud Cloud IDE](https://paiza.cloud/) +2. Créez un compte +3. Cliquez sur *Nouveau Serveur* et choisissez l'application Django +4. Cliquez sur le bouton Terminal (sur le côté gauche de la fenêtre) + +Maintenant vous devriez voir une interface avec une barre latérale et des boutons à gauche. Cliquez sur le bouton « Terminal » pour ouvrir la fenêtre de terminal. Vous devriez voir le résultat suivant : + +{% filename %}Terminal{% endfilename %} + + $ + + +Le terminal de PaizaCloud Cloud IDE attend vos instructions. Vous pouvez redimensionner ou maximiser la fenêtre pour la rendre un peu plus grand. + +#### AWS Cloud9 + +Cloud 9 requiert actuellement que vous vous connectiez avec AWS et que vous renseigniez votre carte de crédit. + +1. Installez Cloud 9 depuis le [Chrome Web Store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Allez à [c9.io](https://c9.io) et cliquez sur *Mise en route avec AWS Cloud9* +3. Créez un compte AWS (requiert votre carte de crédit, mais il existe un forfait gratuit) +4. Dans le tableau de bord AWS, entrez *Cloud9* dans la barre de recherche et cliquez dessus +5. Dans le tableau de bord Cloud 9, cliquez sur *Créer un environnement* +6. Appelez-le *django-girls* +7. Lors de la configuration des paramètres, sélectionnez *Créer une nouvelle instance pour l'environnement (EC2)* pour "Type d'environnement" et le "Type d'instance" *t2.micro* (il devrait être indiqué comme disponible gratuitement). Le paramètre d'économie par défaut suffira. Vous pouvez garder les autres paramètres par défaut. +8. Cliquez sur *Étape suivante* +9. Cliquez sur *Créer un environnement* + +Maintenant, vous pouvez voir une interface avec une barre latérale, une grande fenêtre principale avec du texte et une petite fenêtre en bas qui ressemble à quelque chose comme ceci: + +{% filename %}bash{% endfilename %} + + nomutilisateur:~/workspace $ + + +Cette fenêtre en bas est votre terminal. Vous pouvez l'utiliser pour donner des instructions à l'ordinateur Cloud9. Vous pouvez changer la taille de la fenêtre et l'agrandir un peu. + +#### Glitch.com Cloud IDE + +1. Allez sur [Glitch.com](https://glitch.com/) +2. Créez un compte (https://glitch.com/signup) ou utilisez votre compte GitHub si vous en avez un. (Voir les instructions GitHub ci-dessous.) +3. Cliquez sur *New Project* et choisissez *hello-webpage* +4. Cliquez sur la liste déroulante Outils (en bas à gauche de la fenêtre), puis sur le bouton Terminal pour ouvrir l'onglet terminal qui contiendra une invite comme celle-ci : + +{% filename %}Terminal{% endfilename %} + + app@nom-de-votre-projet-glitch:~ + + +Lorsque vous utilisez Glitch.com comme environnement de développement Cloud (IDE), vous n'avez pas besoin de créer un environnement virtuel. À la place, créez manuellement les fichiers suivants : + +{% filename %}glitch.json{% endfilename %} + +```json +{ + "install": "pip3 install -r requirements.txt --user", + "start": "bash start.sh", + "watch": { + "throttle": 1000 + } +} +``` + +{% filename %}requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +{% filename %}.bash_profile{% endfilename %} + +```bash +alias python=python3 +alias pip=pip3 +``` + +{% filename %}start.sh{% endfilename %} + +```bash +chmod 600 .bash_profile +pip3 install -r requirements.txt --user +python3 manage.py makemigrations +python3 manage.py migrate +python3 manage.py runserver $PORT +``` + +Une fois ces fichiers créés, allez dans le Terminal et exécutez les commandes suivantes pour créer votre premier projet Django : + +{% filename %}Terminal{% endfilename %} + + django-admin.py startproject mysite . + refresh + + +Afin de voir les messages d'erreur détaillés, vous pouvez activer les journaux de débogage Django pour votre application Glitch. Ajoutez simplement ce qui suit à la fin du fichier `mysite/settings.py`. + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'debug.log', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + }, +} +``` + +Cela va créer un fichier `debug.log` détaillant les opérations Django et tous les messages d'erreur qui pourraient apparaître, ce qui rendra la correction beaucoup plus facile si votre site Web ne fonctionne pas. + +Le redémarrage initial du projet Glitch devrait échouer. (Si vous cliquez sur le bouton en haut de la liste déroulante `Show` puis cliquez sur `In a New Window`, vous recevrez un message d'erreur `DisallowedHost` (accès non autorisé).) Ne vous inquiétez pas à ce stade, le tutoriel corrigera cela dès que vous aurez mis à jour les paramètres Django de votre projet dans le fichier `mysite/settings.py` . + +### Environnement virtuel + +Un environnement virtuel (également appelé un virtualenv) est comme une boîte noire dans laquelle nous pouvons insérer du code informatique utile à un projet sur lequel nous travaillons. Nous les utilisons pour conserver séparément les différents morceaux de code que nous voulons dans nos différents projets afin que les choses ne se mélangent entre les projets. + +Lancer : + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3 -m venv myvenv + source myvenv/bin/activate + pip install django~={{ book.django_version }} + + +(Notez que sur la dernière ligne, nous utilisons un tilde suivi d'un signe égal : `~=`). + +### GitHub + +Créez un compte [GitHub](https://github.com). + +### PythonAnywhere + +Le tutoriel Django Girls comprend une section sur ce qui est appelé le Déploiement, un processus qui permet de déplacer le code de votre application web vers un ordinateur public (appelé serveur) pour que d'autres personnes puissent voir votre travail. + +Cette partie est un peu étrange quand on fait le tutoriel sur un Chromebook puisque nous utilisons déjà un ordinateur qui est visible sur Internet (par opposition, par exemple, à un ordinateur portable). Cependant, c'est toujours utile, car nous devons penser à notre espace de travail Cloud 9 comme un endroit pour notre travail "en cours" et Python Anywhere comme un endroit pour publier notre projet à mesure qu'il devient plus complet. + +Donc, inscrivez-vous pour un nouveau compte Python Anywhere sur [www.pythonanywhere.com](https://www.pythonanywhere.com). \ No newline at end of file diff --git a/fr-FR/code_editor/README.md b/fr-FR/code_editor/README.md new file mode 100644 index 00000000000..b3e64c1cad6 --- /dev/null +++ b/fr-FR/code_editor/README.md @@ -0,0 +1,11 @@ +# L'éditeur de code + +> Pour les lectrices autodidactes, ce chapitre est traité dans la vidéo [Installer Python & Éditeur de code](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s). + +Vous êtes sur le point d'écrire vos premières lignes de code, il est donc temps de télécharger un éditeur de code. + +> **Note** Si vous utilisez un Chromebook, ignorez ce chapitre mais assurez-vous de suivre les instructions dans [configuration pour Chromebook](../chromebook_setup/README.md). Le cloud IDE que vous avez choisi (PaizaCloud Cloud IDE ou AWS Cloud9) inclut un éditeur de code, et lorsque vous ouvrez un fichier dans votre IDE dans le menu fichier, vous utiliserez automatiquement l’éditeur. +> +> **Note** Vous l'avez probablement déjà fait au chapitre [Installation](../installation/README.md). Si c'est le cas, vous pouvez passer directement au prochain chapitre ! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/fr-FR/code_editor/instructions.md b/fr-FR/code_editor/instructions.md new file mode 100644 index 00000000000..a7465c92120 --- /dev/null +++ b/fr-FR/code_editor/instructions.md @@ -0,0 +1,37 @@ +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. + +Nos suggestions sont listées ci-dessous, mais n'hésitez pas à demander à vos coachs quelles sont leurs préférences - il sera plus facile d'obtenir de l'aide de leur part. + +## Visual Studio Code + +Visual Studio Code est éditeur de texte développé par Microsoft pour Windows, Linux et macOS. Il inclut le support du déboggage, l'utilisation de Git intégrée, le surlignage syntaxique, l'autocompletion intelligente du code, les snippets et la refactoring du code. + +[Télécharger](https://code.visualstudio.com/) + +## 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 avec une période d'évaluation gratuite et il est disponible pour tous les systèmes d'exploitation. + +[Télécharger](https://www.sublimetext.com/3) + +## Atom + +Atom est un autre éditeur populaire. Il est gratuit, ouvert et disponible pour Windows, macOS et Linux. Atom est développé par [GitHub](https://github.com/). + +[Télécharger](https://atom.io/) + +## Pourquoi installer un éditeur de texte? + +Vous devez vous demander pourquoi on installe un éditeur de texte spécial plutôt que d'utiliser Word ou Notepad plus simplement. + +La première raison est que le code doit être en format **texte brute**, et le problème est que les éditeurs comme Word et Textedit ne produisent pas réellement du texte brute, mais du texte enrichi (avec des polices et de la mise en forme), en utilisant des formats personnalisés comme [ RTF (Rich Text Format) ](https://en.wikipedia.org/wiki/Rich_Text_Format). + +La seconde raison est que les éditeurs de code sont conçus spécialement pour l'édition de code. Ils fournissent donc des fonctionnalités très utiles comme la coloration du code en fonction du sens de celui ou automatiquement ajouter un guillemet fermant à chaque que vous ouvrez un guillemet. + +Nous verrons tout cela en pratique plus tard. Bientôt votre bon vieux éditeur de code deviendra l'un de vos outils favoris. :) \ No newline at end of file diff --git a/fr-FR/css/README.md b/fr-FR/css/README.md new file mode 100644 index 00000000000..8e5c0ad8aa8 --- /dev/null +++ b/fr-FR/css/README.md @@ -0,0 +1,330 @@ +# CSS - Rendez votre site joli ! + +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 (CSS : Cascading Style Sheets) sont un langage utilisé pour décrire l'apparence et la disposition d'un site écrit en langage de balisage (comme HTML). Considérez-le comme le maquillage de notre page web. ;) + +Mais on ne souhaite pas repartir de zéro. Une fois de plus, nous utiliserons quelque chose que les programmeurs ont publié gratuitement sur Internet. Réinventer la roue n'est pas amusant, n'est-ce pas ? + +## Utilisons Bootstrap ! + +Bootstrap est l'un des frameworks HTML/CSS les plus populaires pour développer de beaux sites web : https://getbootstrap.com/ + +Il a été créé par d'anciens développeurs de Twitter. Il est maintenant développé par des bénévoles aux quatre coins du monde ! + +## Installer Bootstrap + +Pour installer Bootstrap, ouvrez votre fichier `.html` dans l'éditeur de code et ajoutez cela à la section `` : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Cela n'ajoute pas de fichier à votre projet, mais crée seulement un lien vers des fichiers existant sur internet. Allez-y, ouvrez votre site web et rafraichissez la page. Et voilà ! + +![Figure 14.1](images/bootstrap1.png) + +C'est déjà un peu mieux ! + +## Les fichiers statiques dans Django + +Enfin, allons jeter un coup d'œil à ces **fichiers statiques** dont nous n'arrêtons pas de vous parler. Les fichiers statiques correspondent à tous vos CSS et vos images. Leur contenu ne dépend pas du contexte de la requête et sera le même pour tous les utilisateurs. + +### Où ranger les fichiers statiques dans Django ? + +Django sait déjà où trouver les fichiers statiques pour l'application "admin" intégrée. Maintenant, nous devons ajouter quelques fichiers statiques pour notre propre application, `blog`. + +Pour cela, nous allons créer un dossier appelé `static` à l'intérieur de notre appli blog : + + djangogirls + ├── blog + │ ├── migrations + │ ├── static + │   └── templates + └── mysite + + +Django va rechercher automatiquement tous les dossiers dits "statiques" à l'intérieur de vos dossiers d'appli. Ensuite, il sera en mesure d'utiliser leur contenu sous forme de fichiers statiques. + +## Votre premier fichier CSS ! + +Nous allons maintenant créer un fichier CSS afin de personnaliser votre page. 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 ? + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +Et c'est parti pour un peu de CSS ! Ouvrez le fichier `blog/static/css/blog.css` dans votre éditeur de texte. + +Nous n'irons pas trop loin dans la personnalisation et l'apprentissage du CSS ici. Il y a à la fin de cette page une recommandation pour un cours CSS gratuit si vous souhaitez en savoir plus. + +Que pourrions-nous faire rapidement ? Pourquoi ne pas changer la couleur de notre en-tête ? Pour indiquer la couleur que nous souhaitons utiliser, nous devons utiliser un code particulier. Ce code commence par un `#` suivi de 6 lettres (A-F) et chiffres (0-9). Par exemple, le code pour du bleu est `#0000FF`. 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](http://www.w3schools.com/colors/colors_names.asp), comme `red` ou `green`. + +Dans votre fichier `blog/static/css/blog.css`, ajoutez le code suivant : + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; +} + +``` + +`h1 a` est un sélecteur CSS. Cela signifie que nous allons appliquer nos styles à tout élément `a` qui se trouve dans un élément `h1` ; le sélecteur `h2 a` fait la même chose pour les éléments `h2`. Donc lorsque nous avons quelque chose comme `

lien

`, le style `h1 a` est appliqué. Dans notre cas, nous indiquons de changer sa couleur en `#C25100`, c'est à dire en orange foncé. Ou vous pouvez mettre votre propre couleur ici, mais assurez-vous qu’il contraste bien avec le fond blanc ! + +Un fichier CSS permet de déterminer le style des éléments présents dans un fichier HTML. La première façon pour identifier des éléments, c'est avec leur nom d'élément. Vous vous en souviendrez car ces noms proviennent des balises HTML. Exemple : `a`, `h1` et `body` sont tous des noms d'élément. Vous pouvez aussi identifier les éléments par leur attribut `class` ou `id`. La classe et l'identifiant sont des noms que vous choisissez vous-même. Les classes définissent des groupes d'éléments tandis que les identifiants pointent un élément spécifique. Par exemple, l'élément suivant peut être identifié par CSS à la fois par son nom `a`, sa classe `external_link`, ou son identifiant unique (id) `link_to_wiki_page` : + +```html + +``` + +Apprenez-en plus à propos des [Sélecteurs CSS sur W3Schools](http://www.w3schools.com/cssref/css_selectors.asp). + +Nous devons aussi dire à notre modèle HTML que nous avons utilisé un peu de CSS. Ouvrez le fichier `blog/templates/blog/post_list.html` dans l'éditeur de code et ajoutez cette ligne au tout début : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} +``` + +On vient tout juste de charger les fichiers statiques :). Entre les balises `` et ``, après les liens vers les fichiers CSS de Bootstrap, ajoutez cette ligne : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Le navigateur lit les fichiers dans l'ordre où ils sont donnés, donc nous devons nous assurer que c'est dans le bon endroit. Dans le cas contraire, le code dans notre fichier peut être écrasé par le code des fichiers Bootstrap. Nous venons simplement de dire à notre template où trouver notre fichier CSS. + +Maintenant, votre fichier doit ressembler à ceci : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +Ok, on sauvegarde et on rafraîchit la page ! + +![Figure 14.2](images/color2.png) + +Bravo ! Peut-être que nous pourrions aérer un peu notre page web en augmentant la marge du côté gauche ? Essayons pour voir ! + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +body { + padding-left: 15px; +} +``` + +Ajoutez ceci à votre CSS, enregistrez le fichier et regarder comment cela fonctionne ! + +![Figure 14.3](images/margin2.png) + +Et si nous changions aussi la police de caractères de notre entête ? Collez ceci dans le `` de votre fichier `blog/templates/blog/post_list.html` : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Comme précédemment, vérifiez l'ordre et placez le avant `blog/static/css/blog.css`. Cette ligne importera une police appelée *Lobster* à partir de Google Fonts (https://www.google.com/fonts). + +Retrouvez le bloc de règles `h1 a` (délimité par les accolades `{` `}`) dans le fichier css `blog/static/css/blog.css`. Ajoutez maintenant la ligne `font-family; 'Lobster',` dans les accolades et rafraîchissez la page : + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +h1 a, h2 a { + color: #C25100; + font-family: 'Lobster'; +} +``` + +![Figure 14.3](images/font.png) + +Super ! + +Comme mentionné ci-dessus, CSS a un concept de classe. Ce concept vous permet de nommer une partie de code HTML et d'y appliquer des styles, uniquement pour cette partie, sans affecter le reste. Cela peut être très utile ! Peut-être que vous avez deux divs qui sont en train de faire quelque chose de différent (comme votre en-tête et votre contenu). Une classe peut vous aider à leur donner un aspect différent. + +Vous pouvez maintenant nommer certaines parties du code HTML. Remplacez l'élément `header` qui contient votre en-tête avec ce qui suit : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + +``` + +Maintenant, ajoutez la classe `post` à votre `article` contenant votre blog post. + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Nous allons maintenant ajouter des blocs de règles aux différents sélecteurs. Les sélecteurs qui commencent par `.` désignent des classes. De nombreux tutoriels et explications sur le CSS existent sur le Web, cela pourra vous aider qui à comprendre le code suivant. Pour le moment, copiez et collez-le dans votre fichier `blog/static/css/blog.css` : + +{% filename %}blog/static/css/blog.css{% endfilename %} + +```css +.page-header { + background-color: #C25100; + margin-top: 0; + margin-bottom: 40px; + 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; +} + +h1, +h2, +h3, +h4 { + font-family: 'Lobster', cursive; +} + +.date { + 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 h2 a, +.post h2 a:visited { + color: #000000; +} + +.post > .date, +.post > .actions { + float: right; +} + +.btn-default, +.btn-default:visited { + color: #C25100; + background: none; + border-color: #C25100; +} + +.btn-default:hover { + color: #FFFFFF; + background-color: #C25100; +} +``` + +Nous allons maintenant nous intéresser au code concernant les posts. Il va falloir remplacer le code le code suivant : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +se trouvant dans le fichier `blog/templates/blog/post_list.html` par : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Sauvegardez les fichiers modifiés et rafraîchissez votre page. + +![Figure 14.4](images/final.png) + +Woohoo ! Ça a l'air génial, non ? Intéressez-vous au code que nous venons juste de coller pour trouver quelles règles CSS sont appliquées aux sélecteurs HTML que nous avons nommés précédemment. Où feriez-vous le changement si l'on souhaite mettre la date en turquoise ? + +N'ayez pas peur de bricoler un peu le CSS et essayer de changer certaines choses. Jouer avec le CSS peut vous aider à comprendre comment et qui agit sur quoi. Si vous cassez quelque chose, ne vous inquiétez pas – vous pouvez toujours faire marche arrière ! + +Nous vous recommandons chaudement de suivre les cours en ligne "Basic HTML & HTML5" et "Basic CSS" sur [freeCodeCamp](https://learn.freecodecamp.org/). Ils vous aideront à en apprendre plus sur le sujet et à créer de magnifiques sites web avec HTML et CSS. + +Prêt pour le chapitre suivant ? :) \ No newline at end of file diff --git a/fr-FR/deploy/README.md b/fr-FR/deploy/README.md new file mode 100644 index 00000000000..67295d98cf3 --- /dev/null +++ b/fr-FR/deploy/README.md @@ -0,0 +1,250 @@ +# Déployer ! + +> **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'à maintenant, votre site web est uniquement disponible sur votre ordinateur. Maintenant, vous allez apprendre à 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 de serveurs disponibles sur Internet, nous utiliserons [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere est gratuit pour les petites applications qui n'ont pas trop de visiteurs, donc ce sera certainement suffisant pour vous maintenant. + +Nous allons aussi utiliser les services [GitHub](https://www.github.com), 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 ! + +Ces trois endroits sont importants pour vous. Votre ordinateur local est l'endroit où vous faites de développement et de test. Lorsque vous êtes heureux avec le résultat, vous sauvegarderez une copie de votre programme sur GitHub. Votre site sera sur PythonAnywhere et vous le mettrez à jour en y mettant une copie de votre nouveau code sur GitHub. + +# Git + +> **Note** Si vous avez déjà effectué [l'installation](../installation/README.md), il n'est pas nécessaire de la refaire : vous pouvez passer à la partie suivante et commencer à créer votre dépôt Git + +{% include "/deploy/install_git.md" %} + +## Démarrer un dépôt Git + +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 : + +> **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`. + +{% filename %}command-line{% endfilename %} + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +L'initialisation d'un dépôt git ne doit être faite qu'une seule fois par projet (et vous n'avez plus jamais besoin de re-saisir le nom d'utilisateur et adresse email). + +Git va surveiller les modifications faites à tous les fichiers et dossiers présents dans ce répertoire, mais il y a certains fichiers que nous voudrions qu'il ignore. 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 : + +{% filename %}.gitignore{% endfilename %} + + # Python + *.pyc + *~ + __pycache__ + + # Env + .env + myvenv/ + venv/ + + # Base de donnée + db.sqlite3 + + # Dossier "static" à la racine du projet + /static/ + + # macOS + ._* + .DS_Store + .fseventsd + .Spotlight-V100 + + # Windows + Thumbs.db* + ehthumbs*.db + [Dd]esktop.ini + $RECYCLE.BIN/ + + # Visual Studio + .vscode/ + .history/ + *.code-workspace + + Text + XPath: /pre[2]/code + + + +Enregistrez ce fichier sous le nom `.gitignore` dans votre répertoire principal "djangogirls". + +> **Attention** : le point au début du nom du fichier est important ! Si vous avez des difficultés à le faire (les Macs n'aiment pas que vous créiez des fichiers commençant par un point dans le Finder, par exemple), utilisez la fonction "Enregistrer sous" dans votre éditeur; ça marche toujours. N'ajoutez pas `.txt`, `.py`, ou d'autres extensions à la fin du nom. Git va reconnaitre le fichier seulement s'il porte le nom `.gitignore`. Linux et MacOS considèrent les fichiers commençant par `.` (comme `.gitignore`) comme étant cachés et la commande `ls` normale ne va pas montrer ces fichiers. Il faut utiliser `ls -a` pour voir le fichier `.gitignore`. +> +> **Remarque** un de fichiers que vous avez spécifié dans votre fichier `.gitignore` est `db.sqlite3`. Ce fichier est votre base de données locale, où tous les utilisateurs et les articles que vous avez créés sont stockés. Suivant les bonnes pratiques du développement web, nous allons utiliser des bases de données distinctes pour votre site de test local et votre site Web en ligne sur PythonAnywhere. La base de données sur PythonAnywhere pourrait être du type SQLite, comme votre version locale. Normalement on lui préfèrerait une base de données du type MySQL, car capable de gérer un plus grand nombre de visiteurs. Quoi qu’il en soit, le fait que votre base de données SQLite soit ignorée lors de l'archivage sur GitHub implique que tous les messages et le superutilisateurs que vous avez créé jusqu'à présent ne seront disponibles que localement. Vous devrez les créer de nouveau en production. Vous devriez penser à votre base de données locale comme un terrain de jeux où vous pouvez tester différentes choses et ne pas avoir peur de supprimer vos messages réels sur votre blog. + +C'est une bonne idée d'utiliser la commande `git status` avant `git add` ou dès que vous n'êtes plus sûr de ce qui a changé dans le projet. Cela vous évitera des surprises comme ajouter ou envoyer un mauvais fichier. La commande `git status` permet d'obtenir des informations sur tous les fichiers non-suivis/modifiés/ajoutés, l'état de la branche, et bien plus encore. La commande devrait renvoyer ceci: + +{% filename %}command-line{% endfilename %} + + $ git status + On branch master + + No commits yet + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + requirements.txt + + nothing added to commit but untracked files present (use "git add" to track) + + +Et pour finir, nous allons enregistrer nos modifications. Tapez ces commandes dans votre terminal: + +{% filename %}command-line{% endfilename %} + + $ git add . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Publier votre code sur GitHub + +Allez sur [GitHub.com](https://www.github.com) et créez-vous un nouveau compte gratuitement. (Si vous l'avez déjà fait lors de la préparation pour l’atelier, c’est très bien !) N’oubliez pas de mémoriser votre mot de passe (ajoutez-le à votre gestionnaire de mot de passe, si vous en utilisez un). + +Ensuite, créez un nouveau dépôt en lui donnant le nom "mon-nouveau-blog". Laissez la case "initialisation avec README" décochée, laissez l'option .gitignore vide (nous l'avons fait manuellement) et laissez la Licence en tant que Aucune. + +![](images/new_github_repo.png) + +> **Note** : dans le cadre de ce tutoriel, le nom `mon-nouveau-blog` est très important. Cependant, vous êtes libre de le changer mais, attention : à chaque fois que ce nom apparaîtra dans le tutoriel, vous allez devoir le remplacer par le nom que vous avez choisi. Il est probablement plus simple de garder le nom `mon-nouveau-blog`. + +Dans l'image suivante, vous verrez le URL de votre dépôt, que vous utiliserez dans certaines commandes qui suivent (ex. pour cloner le dépôt) : + +![](images/github_get_repo_url_screenshot.png) + +Nous avons maintenant besoin de relier nos deux dépôts ("hook" en anglais) : celui sur notre ordinateur et celui sur GitHub. + +Tapez les instructions suivantes dans votre console (remplacez `` avec le nom d'utilisateur de votre compte GitHub et sans les chevrons. Le URL doit correspondre exactement à l'URL que vous venez de voir) : + +{% filename %}command-line{% endfilename %} + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Lorsque vous "poussez" sur GitHub, votre nom d’utilisateur ainsi que le mot de passe vous seront demandés (que ce soit dans la fenêtre de ligne de commande ou dans une fenêtre pop-up). Après avoir entré les informations d’identification, vous devriez voir quelque chose comme ceci : + +{% filename %}command-line{% endfilename %} + + 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/ola/my-first-blog.git + + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +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](https://github.com/django/django), [le tutoriel Django Girls](https://github.com/DjangoGirls/tutorial) et les nombreux autres projets libres qui sont hébergés sur GitHub. :) + +# Mettre votre blog en ligne avec PythonAnywhere + +## Créez votre compte utilisateur sur PythonAnywhere + +> **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. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Configurer votre site sur PythonAnywhere + +Allez sur le [Panneau de Contrôle de PythonAnywhere](https://www.pythonanywhere.com/) en cliquant sur le logo, et choisissez l'option de démarrer un terminal "Bash". C'est comme votre terminal à vous, mais chez PythonAnywhere. + +![La section "nouveau terminal" sur l'interface web de PythonAnywhere, avec un bouton pour "bash"](images/pythonanywhere_bash_console.png) + +> **Note** : PythonAnywhere utilise Linux. Si vous êtes sous Windows, la console sera un peu différente de celle de votre ordinateur. + +Pour déployer une application sur PythonAnywhere, vous devez y télécharger votre code depuis GitHub, puis configurer PythonAnywhere pour qu'il la reconnaisse et commence à la faire tourner en tant qu'application web. Cela peut se faire de façon manuelle, mais PythonAnywhere fourni un outil qui va tout faire pour vous. Commençons par l'installer: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pip3.8 install --user pythonanywhere + + +Vous devriez voir quelque chose comme `Collecting pythonanywhere`, et au bout d'un moment une dernière ligne disant `Successfully installed (...) pythonanywhere-(...)`. + +Maintenant, nous exécutez l'assistant pour configurer automatiquement votre application à partir de GitHub. Tapez ce qui suit dans la console sur PythonAnywhere (n'oubliez pas d'utiliser votre nom d'utilisateur GitHub à la place de ``, afin que l'URL corresponde à celle du clone de GitHub) : + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ pa_autoconfigure_django.py --python=3.8 https://github.com//my-first-blog.git + + +En regardant la commande s'exécuter, vous devriez voir ce qui ce passe: + +- Téléchargement de votre code depuis GitHub +- Création d'un virtualenv chez PythonAnywhere, comme celui sur votre propre ordinateur +- Mise à jour de votre fichier de paramètres avec des paramètres de déploiement +- Mise en place d’une base de données sur PythonAnywhere en utilisant la commande `manage.py migrate` +- Mise en place de vos fichiers statiques (nous verrons ce que c'est plus tard) +- Et configuration de PythonAnywhere pour servir votre application web via son API + +Sur PythonAnywhere toutes ces étapes sont automatisées, mais ce sont les mêmes étapes que vous auriez à faire avec n'importe quel autre fournisseur de serveurs. + +La principale chose à remarquer maintenant est que votre base de donnée sur PythonAnywhere est complètement séparée de votre base de données sur votre propre ordinateur. Cela veut dire qu'elle peut contenir des messages différents et avoir des comptes administrateurs différents. Et donc, exactement comme on l'avait fait sur votre ordinateur, on doit initialiser le compte administrateur avec `createsuperuser`. PythonAnywhere a initialisé votre virtualenv pour vous automatiquement, donc la seule chose que vous avez à faire est d'exécuter: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ python manage.py createsuperuser + + +Entrez les informations pour votre compte administrateur. Mieux vaut utiliser les mêmes que sur votre ordinateur pour éviter toute confusion, sauf si vous voulez utiliser un mot de passe plus sécurisé sur PythonAnywhere. + +Maintenant, si vous voulez, vous pouvez aussi jeter un œil à votre code sur PythonAnywhere en utilisant la commande `ls`: + +{% filename %}PythonAnywhere command-line{% endfilename %} + + (ola.pythonanywhere.com) $ ls + blog db.sqlite3 manage.py mysite requirements.txt static + (ola.pythonanywhere.com) $ ls blog/ + __init__.py __pycache__ admin.py apps.py migrations models.py + tests.py views.py + + +Vous pouvez également accéder à la page "Fichiers" et naviguer à l'aide du navigateur de fichiers PythonAnywhere intégré. (Depuis la page Console, vous pouvez visiter d'autres pages PythonAnywhere en cliquant sur le bouton Menu en haut à droite. Une fois que vous vous trouvez dans une de ces pages, les liens vers les autres pages se trouve en haut.) + +## Vous êtes désormais sur Internet ! + +Votre site devrait maintenant être accessible sur Internet ! Cliquez sur l'onglet "Web" dans PythonAnywhere pour y obtenir un lien. Vous pouvez partagez ce lien avec qui vous voulez. :) + +> **Note** Ce tutoriel est conçu pour les débutants, et pendant le déploiement on a pris quelques raccourcis qui, d'un point de vue de la sécurité, ne sont pas idéaux. Quand vous voudrez aller plus loin dans ce projet, ou commencer un nouveau projet, vous devriez consulter la [Checklist de déploiement pour Django](https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/) pour obtenir des conseils sur comment sécuriser votre site. + +## Conseils en cas de bug + +Si vous constatez une erreur en exécutant le script `pa_autoconfigure_django.py`, voici quelques causes courantes : + +- Oubli de créer votre "jeton API" pour PythonAnywhere. +- Faire une erreur dans votre URL GitHub +- Si vous voyez un message d’erreur indiquant *« Could not find your settings.py »*, vous avez probablement oublié d'ajouter tous vos fichiers sur Git, et/ou vous ne les avez pas envoyé à GitHub. Regardez à nouveau la section Git ci-dessus +- Si vous avez précédemment créé un compte PythonAnywhere et avez rencontré une erreur avec collectstatic, vous avez probablement une version antérieure de SQLite (par ex : 3.8.2) sur votre compte. Dans ce cas, créez un nouveau compte et essayez les commandes présentes dans la section PythonAnywhere ci-dessus. + +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 les logs dans la page [Web](https://www.pythonanywhere.com/web_app_setup/) de PythonAnywhere. Regardez s’il y a des messages d’erreurs ; les plus récents seront en bas du fichier. + +Vous pourrez aussi trouver des astuces pour le débogage sur le site d'aide de[PythonAnywhere](http://help.pythonanywhere.com/pages/DebuggingImportError). + +Et n'oubliez pas, votre coach est là pour vous aider ! + +# Jetez un œil à votre site ! + +La page par défaut de votre site doit dire "Ça marche!", comme c'est le cas sur votre ordinateur local. 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. Identifiez-vous avec votre nom d'utilisateur et mot de passe et vous verrez que vous pourrez créer de nouveaux messages sur le serveur. N'oubliez pas que les messages dans votre base de données locale n'ont pas été envoyés sur la version en ligne de votre blog. + +Une fois que vous avez créé des messages, vous pouvez revenir à votre configuration locale (pas PythonAnywhere). De là, vous devez travailler sur votre installation locale pour apporter des modifications. C'est la façon habituelle de procéder dans le développement web : faire des modifications localement, envoyer ces modifications sur GitHub, puis télécharger ces modifications vers votre serveur Web de production. Cela vous permet de faire des expériences sans endommager votre site web de production (celui sur Internet). Cool, non ? + +*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 à mettre votre site en ligne, dans le vrai Internet ! \ No newline at end of file diff --git a/fr-FR/deploy/install_git.md b/fr-FR/deploy/install_git.md new file mode 100644 index 00000000000..23fb476e80d --- /dev/null +++ b/fr-FR/deploy/install_git.md @@ -0,0 +1,52 @@ +Git est un " système de gestion de versions" utilisé par de nombreux développeurs. 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. Un peu comme la fonction « suivi des modifications » dans les programmes de traitement de texte (par exemple, Microsoft Word ou LibreOffice Writer), mais beaucoup plus puissant. + +## Installer Git + + + +Vous pouvez télécharger Git sur [git-scm.com](https://git-scm.com/). Vous pouvez cliquer sur "suivant" pour toutes les étapes sauf deux : au moment de choisir l'éditeur, sélectionnez Nano ; à l'étape intitulée "Adjusting your PATH environment", sélectionnez "Use Git and optional Unix tools from the Windows Command Prompt" (l'option du bas). Les autres choix par défaut n'ont pas besoin d'être modifiés. Laissez cocher l'option "Checkout Windows-style, commit Unix-style line endings". + +N'oubliez pas de fermer puis relancer l'invite de commande ou la fenêtre Powershell une fois l'installation terminée. + + + +Téléchargez Git sur [git-scm.com](https://git-scm.com/) et suivez les instructions. + +> **Note** Si vous utilisez un OS X 10.6, 10.7 ou 10.8, vous devrez sans doute installer la version de git présente ici : [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/fr-FR/deploy/signup_pythonanywhere.md b/fr-FR/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..13999332854 --- /dev/null +++ b/fr-FR/deploy/signup_pythonanywhere.md @@ -0,0 +1,19 @@ +PythonAnywhere est un service qui permet de faire tourner des programmes en Python sur des serveurs "dans le cloud". Nous allons l'utiliser pour héberger notre site, en direct et sur Internet. + +Nous allons donc mettre le blog que nous sommes en train de construire sur PythonAnywhere. Pour commencer, créez un compte « Débutant » (beginner) sur PythonAnywhere (le niveau gratuit est très bien, vous n’avez pas besoin d’une carte de crédit). + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +![La page de login de PythonAnywhere contenant un bouton pour créer le compte gratuit pour 'Débutant'](../deploy/images/pythonanywhere_beginner_account_button.png) + +> **Note** Lorsque vous choisissez votre nom d'utilisateur, gardez à l'esprit que l'URL de votre blog prendra la forme `nomutilisateur.pythonanywhere.com`, alors choisissez un pseudonyme ou un nom adapté pour votre blog. Mémorisez votre mot de passe (ajoutez-le à votre gestionnaire de mot de passe, si vous en utilisez un). + +## Création d’un jeton API pour PythonAnywhere + +C'est quelque chose que vous n'aurez à faire qu'une seule fois. Lorsque vous serez inscrit à PythonAnywhere, vous vous retrouverez sur votre tableau de bord. Trouvez le lien en haut à droit de votre page "Compte": + +![Lien du compte en haut à droite sur la page](../deploy/images/pythonanywhere_account.png) + +sélectionnez l'onglet nommé "API token", et cliquez sur le bouton "Créer un nouveau jeton API". + +![L'onglet API sur la page Compte](../deploy/images/pythonanywhere_create_api_token.png) \ No newline at end of file diff --git a/fr-FR/django/README.md b/fr-FR/django/README.md new file mode 100644 index 00000000000..62674aa7890 --- /dev/null +++ b/fr-FR/django/README.md @@ -0,0 +1,27 @@ +# Qu'est-ce que Django? + +Django (*/ˈdʒæŋɡoʊ/ jang-goh*) est un framework web gratuit et open-source écrit en Python. Un framework web est un ensemble de composants qui vous aide à développer des sites web plus rapidement et plus facilement. + +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. + +Heureusement pour vous, d'autres personnes ont réalisé depuis longtemps que les développeurs web font face aux mêmes problèmes lors de la construction d'un nouveau site, donc ils travaillent ensemble et créent un framework (Django étant un) qui vous donne des composants prêts à l'emploi. + +Les frameworks existent pour vous éviter d'avoir à réinventer la roue et aider à réduire les frais généraux lorsque vous construisez de nouveaux sites. + +## Pourquoi est-ce que vous auriez besoin d'un framework ? + +Pour comprendre ce qu'est exactement Django, nous devons regarder de plus près le serveur. La première chose est que le serveur doit savoir que vous voulez vous servir une page Web. + +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 et renvoie une page Web en réponse. Généralement, lorsque vous voulez envoyer quelque chose, vous avez besoin de contenu. Django est un outil qui va vous aider à créer ce contenu. + +## Que se passe-t-il quand quelqu'un demande un site web à votre serveur ? + +Lorsqu'une requête arrive sur un serveur web, elle est transmise à Django dont le premier travail va être de comprendre ce qui est demandé. Il s'occupe tout d'abord de l'adresse de page Web et essaie de savoir quoi faire. Ce travail est effectué par le routeur de Django, l'**urlresolver** (à savoir qu'une adresse web est appelé URL - Uniform Resource Locator - d'où le nom d'*urlresolver*). Ce n'est pas très intelligent - il faut renseigner une liste de modèles pour faire correspondre une URL. Django vérifie dans l'ordre les modèles, et si correspondance il y a, alors il transmet la requête à la fonction associée (appelé *vue*). + +Afin d'y voir un peu plus clair, imaginez un facteur transportant une lettre. Il descend la rue et vérifie à chaque maison si le numéro de celle-ci correspond à celui de la lettre. Si les deux numéros correspondent, il 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 de la *vue* que les choses se passent : nous allons pouvoir jeter un œil dans la base de données pour obtenir d'avantage d'informations. Par exemple, peut-être que l'utilisateur demande à 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, la *vue* générera une réponse de type "Travail terminé !" que Django pourra retourner à l'utilisateur. + +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. + +Au lieu de vous assommer avec des détails complexes, nous allons plutôt commencer à construire quelque chose avec Django et nous allons apprendre les choses importantes au fur et à mesure ! \ No newline at end of file diff --git a/fr-FR/django_admin/README.md b/fr-FR/django_admin/README.md new file mode 100644 index 00000000000..c2d063a88b9 --- /dev/null +++ b/fr-FR/django_admin/README.md @@ -0,0 +1,57 @@ +# Django admin + +Pour ajouter, modifier et supprimer les posts que nous venons de créer, nous allons utiliser l'interface Django admin. + +Ouvrons le fichier `blog/admin.py` dans l'éditeur de code et remplaçons son contenu par ceci : + +{% filename %}blog/admin.py{% endfilename %} + +```python +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)`. + +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. Retourner sur votre navigateur et taper l'adresse http://127.0.0.1:8000/admin/. Vous verrez une page de login qui ressemble à celle-ci : + +![Page de login](images/login_page2.png) + +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. + +> Conseil : pour pouvoir taper de nouvelles commandes pendant que le serveur tourne, ouvrez une nouvelle console et activez à nouveau votre virtualenv. La section **Démarrer le serveur web** du chapitre **Votre premier projet Django !** explique comment écrire de nouvelles commandes. + +{% filename %}Mac OS X or Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +Tapez votre nom d'utilisateur (en minuscules, sans espace), votre email et votre mot de passe. **Ne soyez pas surpris de ne pas voir le mot de passe quand vous le saisissez, c'est normal.** Saisissez le à l'aveugle et appuyez sur `Entrée` pour continuer. Vous devrez obtenir quelque chose comme ceci (où le nom d'utilisateur et le mail correspond à ce que vous avez saisi) : + + Username: ola + Email address: ola@example.com + Password: + Password (again): + Superuser created successfully. + + +Retournez dans votre navigateur et connectez-vous en tant que superutilisateur grâce à l'utilisateur que vous venez de créer. Vous devriez accéder à l'interface d'administration de Django. + +![Django admin](images/django_admin3.png) + +Allons du côté des Posts et jouons un peu avec. Créez 5 ou 6 blog posts. Ne vous inquiétez pas trop du contenu, qui ne sera visible que depuis votre ordinateur. Vous pouvez copier-coller des morceaux du tutoriel pour aller plus vite. :) + +Assurez-vous quelques posts (mais pas tous) aient une date de publication. Cela sera utile plus tard. + +![Django admin](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/2.2/ref/contrib/admin/ + +Cela peut être un bon moment pour prendre un café (ou un thé) ou quelque chose à manger pour vous redynamiser. Vous avez créé votre premier modèle Django - vous méritez une petite pause! \ No newline at end of file diff --git a/fr-FR/django_forms/README.md b/fr-FR/django_forms/README.md new file mode 100644 index 00000000000..97c9cf19845 --- /dev/null +++ b/fr-FR/django_forms/README.md @@ -0,0 +1,479 @@ +# Formulaires Django + +La dernière chose que nous voulons faire sur notre site web, c'est créer une manière sympathique d'ajouter ou éditer des blog posts. L'interface d'administration (`/admin`) de Django est cool, mais elle est assez complexe à personnaliser et à rendre jolie. Les formulaires (`forms`) 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 la seconde solution que nous allons utiliser pour créer un formulaire pour notre modèle `Post`. + +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 + + +Ouvrez maintenant ce fichier dans l'éditeur de code et tapez le code suivant : + +{% filename %}blog/forms.py{% endfilename %} + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Tout d'abord, nous avons besoin d'importer les formulaires Django (`from django import forms`), puis notre modèle `Post` (`from .models import Post`). + +Comme vous l'avez probablement deviné, `PostForm` est le nom de notre formulaire. Nous avons besoin d'indiquer à Django que ce formulaire est un `ModelForm` (pour que Django fasse certaines choses automatiquement pour nous). Pour cela, nous utilisons `forms.ModelForm`. + +Ensuite, nous avons la `class Meta` qui nous permet de dire à Django quel modèle il doit utiliser pour créer ce formulaire (`model = Post`). + +Enfin, nous précisions quel⋅s 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 connecté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. + +Nous allons donc une nouvelle fois suivre le processus suivant et créer : un lien vers la page, une URL, une vue et un template. + +## Lien vers une page contenant le formulaire + +Avant d'ajouter le lien, nous avons besoin d'icônes que nous allons utiliser comme boutons pour le lien. Pour ce tutoriel, téléchargez [file-earmark-plus.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/file-earmark-plus.svg) et enregistrez-le dans le dossier `blog/templates/blog/icons/` + +> Remarque : Pour télécharger l'image SVG, ouvrez le menu contextuel du lien (en cliquant avec le bouton droit de la souris) et sélectionnez "Enregistrer le lien sous". Dans la boîte de dialogue vous demandant où enregistrer le fichier, choisissez le répertoire `djangogirls` de votre projet Django, et à l'intérieur du sous-répertoire `blog/templates/blog/icons/`, et enregistrez le fichier à cet endroit. + +Il est temps d'ouvrir `blog/templates/blog/base.html` dans l'éditeur de code. Maintenant nous pouvons utiliser ce fichier d'icônes à l'intérieur du template de base comme suit. Dans l'élément `div` à l'intérieur de la section `header` , nous ajouterons un lien avant l'élément `h1`: + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Remarquez que notre nouvelle vue s'appelle `post_new`. L'icône [SVG](https://icons.getbootstrap.com/icons/file-earmark-plus/) est fournie par les [icônes Bootstrap](https://icons.getbootstrap.com/) et elle affichera une icône de page avec le signe plus. Nous utilisons une directive de modèle Django appelée `include`. Cela injectera le contenu du fichier dans le template Django. Le navigateur web sait comment gérer ce type de contenu sans aucun traitement supplémentaire. + +> Vous pouvez télécharger toutes les icônes Bootstrap [ici](https://github.com/twbs/icons/releases/download/v1.1.0/bootstrap-icons-1.1.0.zip). Décompressez le fichier et copiez tous les fichiers image SVG vers un nouveau dossier dans `blog/templates/blog/` intitulé `icons`. De cette façon, vous pouvez accéder à une icône comme `pencil-fill.svg` en référençant le chemin du fichier `blog/templates/blog/icons/pencil-fill.svg` + +Après avoir ajouté cette ligne, votre fichier HTML devrait maintenant ressembler à ceci : + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Normalement, après avoir sauvegardé et rechargé la page http://127.0.0.1:8000, vous devriez encore tomber sur l'erreur `NoReverseMatch`. Est-ce le cas ? Très bien ! + +## URL + +Ouvrez le fichier `blog/urls.py` dans l'éditeur de code et ajoutez cette ligne : + +{% filename %}blog/urls.py{% endfilename %} + +```python +path('post/new/', views.post_new, name='post_new'), +``` + +Votre fichier doit maintenant ressembler à ceci : + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), + path('post/new/', views.post_new, name='post_new'), +] +``` + +Une fois la page rechargée, vous allez voir une `AttributeError`, ce qui est normal. Nous n'avons pas encore implémenté la vue `post_new`. Faisons-le maintenant. + +## La vue post_new + +Ouvrez maintenant le fichier `blog/views.py` dans l'éditeur de code et ajoutez les lignes suivantes avec celles du `from` qui existent déjà : + +{% filename %}blog/views.py{% endfilename %} + +```python +from .forms import PostForm +``` + +Puis dans la *vue* : + +{% filename %}blog/views.py{% endfilename %} + +```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 à présent besoin de créer un fichier `post_edit.html` dans le dossier `blog/templates/blog` et de l'ouvrir dans l'éditeur de code. 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 {% raw %}`{{ form.as_p }}`{% endraw %}. +* La ligne précédente va avoir besoin d'être entourée des balises HTML `...`. +* Nous avons besoin d'un bouton `Valider`. Nous allons le créer à l'aide d'un bouton HTML : ``. +* 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 ! Si vous oubliez ce détail, Django se plaindra lorsque vous essaierez de sauvegarder le formulaire: + +![CSFR Forbidden page](images/csrf2.png) + +Ok, voyons maintenant à quoi devrait ressembler le HTML contenu dans le fichier `post_edit.html` : + +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Rafraîchissons la page ! Et voilà : le formulaire s'affiche ! + +![New form](images/new_form2.png) + +Mais attendez une minute! Lorsque vous taperez quelque chose dans les champs `title` et `text` et essayez de le sauvegarder, que se passera-t-il? + +Absolument rien ! Nous retombons sur la même page sauf qu'en plus, notre texte a disparu et aucun article ne semble avoir été créé. Que s'est-il passé ? + +La réponse est : rien ! Nous avons juste encore un peu de travail à accomplir. Retournons à notre *vue*. + +## Sauvegarder le contenu du formulaire + +Ouvrez à nouveau `blog/views.py` dans l'éditeur de code. Actuellement, `post_new` n'est composé que des lignes de code suivantes : + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Lorsque nous envoyons notre formulaire, nous revenons à la même vue. Cependant, nous récupérons les données dans `request`, et plus particulièrement dans `request.POST` (le nom "POST" n'a aucun lien avec nos "posts" de blog : il est lié au type de requête effectué à l'envoi des données). Vous rappelez-vous comment dans le fichier HTML, notre définition de la variable `
` avait la méthode `method="POST"`? 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. + +Donc dans notre *vue* nous avons deux situations différentes à gérer : la première quand on accède à la page pour la première fois et nous voulons un formulaire vide, et la seconde quand on revient à la *vue* avec les données que l'on a saisies dans le formulaire. Pour gérer ces deux cas, nous allons utiliser une condition `if` (si) : + +{% filename %}blog/views.py{% endfilename %} + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +Il faut maintenant remplir à l'endroit des pointillés `[...]`. Si `method` contient `POST` alors on veut construire le `PostForm` avec les données du formulaire, n'est-ce pas ? Nous allons le faire comme cela : + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST) +``` + +La prochaine étape est de vérifier que le formulaire a été rempli correctement (tous les champs obligatoires ont été remplis et aucune valeur incorrecte n'a été envoyée). Nous allons faire ça en utilisant `form.is_valid()`. + +Testons donc si notre formulaire est valide et, si c'est le cas, sauvegardons-le ! + +{% filename %}blog/views.py{% endfilename %} + +```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 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 d'abord ajouter un auteur. La plupart du temps, vous utiliserez `form.save()` sans `commit=False`. Mais ici nous en avons besoin. `post.save()` sauvegardera les changements, c'est-à-dire l'ajout d'un auteur. Et voilà, un nouveau post de blog est créé ! + +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 : + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import redirect +``` + +Ajoutez-le au tout début de votre fichier. Maintenant, nous allons ajouter la ligne qui signifie "aller à la page `post_detail` pour le nouveau post qui vient d'être créé": + +{% filename %}blog/views.py{% endfilename %} + +```python +return redirect('post_detail', pk=post.pk) +``` + +`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 montrions à quoi ressemble maintenant notre *vue* ? + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Voyons si ça marche. Allez à l'adresse http://127.0.0.1:8000/post/new/, ajoutez des valeurs dans les champs `title` et du `text`, 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 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'une des extensions du tutoriel Django Girls** (en anglais). + +Encore bravo ! + +> Comme nous avons récemment utilisé l'interface d'administration de Django, le système pense que nous sommes toujours 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. + +![Logged in error](images/post_create_error.png) + +## Validation de formulaire + +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 ! + +![Form validation](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 notre modèle. C'est cool, non ? + +## Éditer un formulaire + +Maintenant, nous savons comment ajouter un nouveau post. Comment faire pour en modifier un qui existe déjà ? C'est très similaire à ce que nous venons de faire. Tout d'abord, faisons rapidement quelques choses importantes. (Si vous ne comprenez pas quelque chose, vous devriez demander à votre entraîneur ou regarder les chapitres précédents, car nous avons déjà traité toutes ces étapes.) + +Tout d'abord, enregistrons l'icône qui représente le bouton d'édition. Téléchargez [pencil-fill.svg](https://raw.githubusercontent.com/twbs/icons/main/icons/pencil-fill.svg) et enregistrez-le dans le dossier `blog/templates/blog/icons/`. + +Ouvrez `blog/templates/blog/post_detail.html` dans l'éditeur de code et ajoutez le code suivant dans l'élément `article`: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Votre template doit maintenant ressembler à ceci : + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + +{% endblock %} +``` + +Ouvrez le fichier `blog/urls.py` dans l'éditeur de code et ajoutez cette ligne : + +{% filename %}blog/urls.py{% endfilename %} + +```python + path('post//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` dans l'éditeur de code et ajoutons à la toute fin du fichier : + +{% filename %}blog/views.py{% endfilename %} + +```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}) +``` + +Vous ne trouvez pas que ça ressemble presque exactement à 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 passons ce post comme une `instance`, d'abord lorsque nous sauvegardons le formulaire… + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(request.POST, instance=post) +``` + +…Puis ensuite lorsque nous ouvrons le formulaire associé à ce post afin de l'éditer : + +{% filename %}blog/views.py{% endfilename %} + +```python +form = PostForm(instance=post) +``` + +Alors, voyons si ça marche ! Allons à la page `post_detail`. Un bouton d'édition devrait apparaître dans le coin supérieur droit de la page : + +![Edit button](images/edit_button2.png) + +Lorsque vous cliquez dessus, vous devez voir le formulaire du post de blog apparaître : + +![Edit form](images/edit_form2.png) + +N'hésitez pas à changer le titre ou le texte et à enregistrer les modifications! + +Bravo ! Votre application s'enrichit de plus en plus de fonctionnalités ! + +Si vous souhaitez en apprendre plus sur les formulaires Django, n'hésitez pas à consulter la documentation associée : https://docs.djangoproject.com/en/2.2/topics/forms/ + +## Sécurité + +C’est génial de pouvoir créer de nouveaux posts juste en cliquant sur un lien ! Mais maintenant, toute personne visitant votre site sera en mesure de créer un nouveau post, et ce n'est peut-être pas ce que vous voulez. Faisons en sorte que les boutons apparaissent pour vous mais pas pour les autres. + +Ouvrez `blog/templates/blog/base.html` dans l'éditeur de code, trouvez notre `div` `page-header` et la balise ancre que vous y avez mis plus tôt. Ça doit ressembler à ça : + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + {% include './icons/file-earmark-plus.svg' %} + +``` + +Nous allons y ajouter une autre balise `{% if %}` qui ne fera apparaitre le lien qu’aux utilisateurs⋅trices connecté⋅e⋅s avec les droits d'administration. C'est à dire pour le moment, seulement vous ! Changez la balise `` comme ceci : + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/file-earmark-plus.svg' %} + +{% endif %} +``` + +Ce `{% if %}` fait en sorte de n’envoyer le lien au navigateur que si l’utilisateur⋅trice demandant la page est connecté⋅e. Cela ne n'empêche pas complètement la création de nouveaux posts, mais c’est un bon début. Nous reviendrons sur les questions de sécurité dans les extensions du tutoriel. + +Rappelez-vous l'icône de modification que nous venons d'ajouter à notre page de détails? Nous souhaitons également ajouter les mêmes modifications, afin que les autres utilisateurs ne puissent pas modifier les publications existantes. + +Ouvrez le fichier `blog/templates/blog/post_detail.html` dans l'éditeur de code et trouvez la ligne suivante : + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + + {% include './icons/pencil-fill.svg' %} + +``` + +Changez-la en ceci: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + + {% include './icons/pencil-fill.svg' %} + +{% endif %} +``` + +Parce vous êtes sans doute déjà connecté⋅e⋅s, vous ne verrez aucune différence si vous rafraîchissez la page. Mais si vous chargez la page dans un navigateur web différent ou dans une fenêtre en mode "navigation privée" ou "incognito", vous verrez que le lien ne s'affiche plus, et l’icône non plus ! + +## Encore un petit effort : déployons ! + +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: + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git pus + + +* Puis, dans la console bash de [PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +{% filename %}Ligne de commande PythonAnywhere{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(N’oubliez pas de remplacer `` avec votre propre sous-domaine PythonAnywhere, sans les chevrons.) + +* Enfin, allez sur ["Web" page](https://www.pythonanywhere.com/web_app_setup/) (utilisez le bouton de menu en haut à droite de la console) et cliquez **Reload**. Actualisez votre blog https://subdomain.pythonanywhere.com pour voir les changements. + +Et normalement c'est tout ! Félicitations ! :) \ No newline at end of file diff --git a/fr-FR/django_installation/README.md b/fr-FR/django_installation/README.md new file mode 100644 index 00000000000..9e0e85acc8a --- /dev/null +++ b/fr-FR/django_installation/README.md @@ -0,0 +1,7 @@ +# Installation de Django + +> **Note** Si vous utilisez un Chromebook, passez ce chapitre mais prenez soin de suivre les instructions de [configuration pour Chromebook](../chromebook_setup/README.md). +> +> **Note **Si vous avez déjà effectué [l'Installation](../installation/README.md) vous devriez déjà avoir fait ce qui suit. Vous pouvez donc passer directement au chapitre suivant ! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/fr-FR/django_installation/instructions.md b/fr-FR/django_installation/instructions.md new file mode 100644 index 00000000000..09f5715f857 --- /dev/null +++ b/fr-FR/django_installation/instructions.md @@ -0,0 +1,229 @@ +> 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 répertoire "home" par exemple. Sous Windows, le home ressemble à `C:\Utilisateurs\Nom` (où `Nom` est votre login). + +> **Note:** Sur Windows, assurez-vous que le chemin vers ce répertoire ne contienne pas d'accents ou autres caractères spéciaux; si c'est la cas, utilisez un répertoire différent, par exemple `C:\djangogirls`. + +Dans ce tutoriel, nous allons utiliser un nouveau dossier `djangogirls` que vous allez créer dans votre dossier home : + +{% filename %}command-line{% endfilename %} + + $ mkdir djangogirls + $ cd djangogirls + + +Nous allons créer un virtualenv appelé `myvenv`. Pour cela, nous taperons une commande qui ressemblera à : + +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + + + +Pour créer un nouveau `virtualenv`, vous devez ouvrir un terminal et exécuter `python -m venv myvenv`. Voici ce à quoi ça devrait ressembler: + +{% filename %}command-line{% endfilename %} + + C:\Users\Name\djangogirls> python -m venv myvenv + + +Où `myvenv` est 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. It is also a good idea to keep the name short – you'll be referencing it a lot! + + + + + +Pour créer un `virtualenv` sous Linux ou OS X, tapez simplement la commande `python3 -m venv myvenv`. Ça ressemblera à ça : + +{% filename %}command-line{% endfilename %} + + $ 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:** sur certaines versions de Debian/Ubuntu vous pouvez avoir l'erreur suivante: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> Dans ce cas, suivez les instructions ci-dessus et installez le paquet `python9-venv`: {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python3-venv +> +> +> **Note:** Sur certaines version de Debian/Ubuntu, initialiser l’environnement virtuel de cette façon donne l'erreur suivante: +> +> {% filename %}command-line{% endfilename %} +> +> 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`. +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt install python-virtualenv +> $ virtualenv --python=python{{ book.py_version }} myvenv +> +> +> **Note:** Si vous avez une erreur telle que : +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv +> +> +> alors exécutez plutôt : +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python{{ book.py_version }}-venv +> + + + +## Travailler avec virtualenv + +The command above will create a directory called `myvenv` (or whatever name you chose) that contains our virtual environment (basically a bunch of directories and files). + + + +Démarrez votre environnement virtuel en exécutant : + +{% filename %}command-line{% endfilename %} + + C:\Utilisateurs\Nom\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** On Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. Dans ce cas ouvrez une autre console Windows PowerShell avec l'option "ouvrir en tant qu'administrateur". Puis essayer d'exécuter la commande suivante avant de démarrer votre environnement virtuel : +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + + + +> **NOTE:** For users of the popular editor VS Code, which comes with an integrated terminal based off windows PowerShell, if you wish to stick with the integrated terminal, you may run the following command to activate your virtual environment: +> +> $ . myvenv\Scripts\activate.ps1 +> +> +> L'avantage, c'est que vous n'aurez pas à constamment passer de l'éditeur aux lignes de commandes + + + + + +Démarrez votre environnement virtuel en exécutant : + +{% filename %}command-line{% endfilename %} + + $ 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:** If the command `source` is not available, try doing this instead: +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate +> + + + +Vous saurez que votre `virtualenv` est lancé quand le prompt de votre console est précédé de `(myvenv)`. + +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 {#django} + +Maintenant que vous avez activé votre `virtualenv`, vous pouvez installer Django. + +Avant de faire cela, nous devons nous assurer que nous avons la dernière version de `pip`, le programme que nous allons utiliser pour installer Django: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ python -m pip install --upgrade pip + + +### Installer des paquets avec un fichier "requirements" + +Un fichier "requirement" maintient une liste des dépendances qui doivent être installées avec `pip install`: + +Tout d'abord, créez un fichier `requirements.txt` dans votre dossier `djangogirls`, en utilisant l'éditeur de texte que vous avez téléchargé précédemment. Pour ce faire, ouvrez un nouveau fichier dans l'éditeur et sauvegarde-le à l'intérieur du dossier `djangogirls/` en lui donnant le nom `requirements.txt`. Votre dossier ressemble maintenant à ceci : + + djangogirls + ├── myvenv + │ └── ... + └───requirements.txt + + +Dans ce fichier `djangogirls/requirements.txt` vous devez ajouter ceci : + +{% filename %}djangogirls/requirements.txt{% endfilename %} + + Django~={{ book.django_version }} + + +Maintenant, exécutez `pip install -r requirements.txt` pour installer Django. + +{% filename %}command-line{% endfilename %} + + (myvenv) ~$ pip install -r requirements.txt + Collecting Django~={{ book.django_version }} (from -r requirements.txt (line 1)) + Downloading Django-{{ book.django_version }}-py3-none-any.whl (7.1MB) + Installing collected packages: Django + Successfully installed Django-{{ book.django_version }} + + + + +> If you get an error when calling pip on Windows, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\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`). Créez un nouvel environnement virtuel dans le nouveau répertoire, puis supprimez l'ancien et ré-essayez la commande précédente. (Déplacer ou couper/coller le répertoire de l'environnement virtuel ne marchera pas car virtualenv utilise des chemins absolus) + + + + + +> Your command line might freeze when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install -r requirements.txt +> + + + + + +> 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 ! \ No newline at end of file diff --git a/fr-FR/django_models/README.md b/fr-FR/django_models/README.md new file mode 100644 index 00000000000..55240f7db44 --- /dev/null +++ b/fr-FR/django_models/README.md @@ -0,0 +1,201 @@ +# Les modèles dans Django + +Maintenant, nous aimerions créer quelque chose qui permet stocker les articles de notre blog. Mais avant de pour pouvoir faire ça, nous allons tout d'abord devoir vous parler d'un truc qui s'appelle les `objets`. + +## Les objets + +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 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 des propriétés comme `couleur`, `âge`, `humeur` (bonne humeur, mauvaise humeur, fatigué ;)) et `propriétaire` (ce qui pourrait être un objet `Personne`, ou, s'il s'agit d'un chat sauvage, cette propriété pourrait être simplement vide). + +Ensuite, nous pouvons donner des actions au `Chat` : `ronronner`, `gratter` ou `manger`. (Dans ce dernier cas, on donne au chat de la `NourriturePourChat`, ce qui peut être un objet séparé avec ses propres propriétés, comme le `goût`). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +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 devrait-il avoir ? + +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 + -------- + title + text + author + created_date + published_date + + +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 avons une idée de ce que nous avons besoin. Allons modéliser tout ça dans Django! + +## Les modèles dans Django + +Maintenant que nous savons ce qu'est un objet, nous allons pouvoir créer un modèle Django pour notre post de blog. + +Un modèle Django est un type particulier d'objet : il est sauvegardé dans la `base de données`. Une base de données est une collection de données. C'est à cet endroit que l'on stocke toutes les informations au sujet des utilisateurs, des blog posts, etc. Pour stocker nos données, nous allons utiliser une base de données SQLite. C'est la base de données par défaut dans Django. Elle sera largement suffisante pour ce que nous voulons faire. + +Pour vous aider à visualiser ce qu'est une base de données, pensez à un tableur avec des colonnes (champs) et des lignes (données). + +### Créer une application + +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`) : + +{% filename %}Mac OS X and Linux:{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog + + +Vous pouvez voir qu'un nouveau dossier `blog` a été créé et qu'il contient différents fichiers. Les dossiers et fichiers liés à votre projet doivent maintenant être organisés selon cette structure : + + djangogirls + ├── blog + │   ├── admin.py + │   ├── apps.py + │   ├── __init__.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 + ├── manage.py + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + + +Après avoir créé une nouvelle application, vous devez dire à Django de l'utiliser. Nous faisons cela via le fichier `mysite/settings.py`. Ouvrez-le dans votre éditeur de code. Trouvez la section `INSTALLED_APPS` et ajoutez une ligne `'blog.apps.BlogConfig',` juste avant `]`. La section doit maintenant ressembler à ceci : + +{% filename %}mysite/settings.py{% endfilename %} + +```python +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog.apps.BlogConfig', +] +``` + +### 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 que c'est qu'un un blog post. + +Ouvrez le fichier `blog/models.py` dans l'éditeur de code, supprimez tout ce qui s'y trouve et copiez-y le morceau de code suivant : + +{% filename %}blog/models.py{% endfilename %} + +```python +from django.conf import settings +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + 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 (ce qui 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 des caractères spéciaux ou accentués et 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 que c'est du texte? Un nombre ? Une date ? Une relation à un autre objet, comme un objet utilisateur par exemple ?) + +- `models.CharField` - Cela nous permet de définir un champ texte avec un nombre limité de caractères. +- `models.TextField` - Cela nous permet de définir un champ text sans limite de caractères. Parfait pour le contenu d'un blog post, non ? +- `models.DateTimeField` - Définit que le champ en question est un horodatage (date et 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/2.2/ref/models/fields/#field-types). + +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. La règle de nommage est d'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 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. + +Notez également que les deux lignes `def publish(self) :` et `def __str__(self) :` sont mises en retrait à l’intérieur de notre classe. Parce que Python est sensible aux espaces, nous devons mettre en retrait (ou "indenter") nos méthodes à l'intérieur de la classe. Sinon, les méthodes ne sont pas considérées comme appartenantes à la classe, et vous pouvez obtenir un comportement inattendu. + +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 devons signaler à Django que nous venons de créer notre modèle. (Nous venons de le terminer !). Allez sur votre terminal et tapez `python manage.py makemigrations blog`. Le résultat devrait ressembler à ça : + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + blog/migrations/0001_initial.py: + + - Create model Post + + +**Remarque :** N’oubliez pas de sauvegarder les fichiers que vous modifiez. Dans le cas contraire, votre ordinateur exécute la version précédente, ce qui pourrait vous donner des messages d’erreur inattendus. + +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 : + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + 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 diff --git a/fr-FR/django_orm/README.md b/fr-FR/django_orm/README.md new file mode 100644 index 00000000000..89bb1a8927a --- /dev/null +++ b/fr-FR/django_orm/README.md @@ -0,0 +1,221 @@ +# 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 ! + +## Qu'est-ce qu'un QuerySet ? + +Un QuerySet est, par essence, une liste d'objets d'un modèle donné. C'est ce qui vous permet de lire, trier et organiser, des données présentes dans une base de données. + +Il est plus simple d'apprendre avec un exemple. Et si nous nous intéressions à celui-ci ? + +## Le shell Django + +Ouvrez la console de votre ordinateur (et non celle de PythonAnywhere) et tapez la commande suivante : + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py shell + + +Ceci devrait maintenant s'afficher dans votre console : + +{% filename %}command-line{% endfilename %} + +```python +(InteractiveConsole) +>>> +``` + +Vous êtes maintenant dans la console interactive de Django. C'est comme celle de Python, mais avec toute la magie qu'apporte Django :). Les commandes Python sont aussi utilisables dans cette console. + +### Lister tous les objets + +Essayons tout d'abord d'afficher tous nos posts. Vous pouvez le faire à l'aide de cette commande : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Oups ! 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" ! + +{% filename %}command-line{% endfilename %} + +```python +>>> from blog.models import Post +``` + +Nous importons le modèle `Post` depuis notre `blog.models`. Essayons à nouveau la commande précédente : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, ]> +``` + +Cela nous permet d'obtenir une liste des posts que nous avons créés 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 + +Voici comment créer un nouveau objet Post dans la base de données : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +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 : + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.contrib.auth.models import User +``` + +Avons-nous des utilisateurs dans notre base de données ? Voyons voir : + +{% filename %}command-line{% endfilename %} + +```python +>>> User.objects.all() +]> +``` + +Il s'agit du superutilisateur que nous avons créé tout à l'heure ! Sauvegardons une instance de cet utilisateur (modifie la ligne suivante avec ton nom d'utilisateur) : + +{% filename %}command-line{% endfilename %} + +```python +>>> me = User.objects.get(username='ola') +``` + +Comme vous pouvez le constater, nous avons maintenant obtenu (`get`) un utilisateur (`User`) avec un nom d’utilisateur `username` qui est égale à « ola ». Très bien ! + +Nous allons enfin pouvoir créer notre post : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') + +``` + +Et voilà ! Vous aimeriez voir si ça a vraiment marché ? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.all() +, , ]> +``` + +Et voilà : un post de plus dans la liste ! + +### Ajouter plus de posts + +Amusez-vous à ajouter d'autres posts pour vous entrainer un peu. Essayez d'ajouter deux ou trois posts en plus puis passez à la partie suivante. + +### Filtrer les objets + +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, la condition est que `author` soit égal à `me`. La manière de le dire en Django c'est : `author=me`. Maintenant, votre bout de code doit ressembler à ceci : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(author=me) +, , , ]> +``` + +Et si nous voulions chercher les posts qui contiennent uniquement le mot "titre" ("title" en anglais) dans le champs `title`? + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(title__contains='title') +, ]> +``` + +> **Note** Il y a deux tirets bas (`_`) entre `title` et `contains`. L'ORM de Django utilise cette règle 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 filtrer les posts qui possèdent une date de publication (`published_date`) dans le passé : + +{% filename %}command-line{% endfilename %} + +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) + +``` + +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 : + +{% filename %}command-line{% endfilename %} + +```python +>>> post = Post.objects.get(title="Sample title") +``` + +Ensuite, publions-le grâce à notre méthode `publish`: + +{% filename %}command-line{% endfilename %} + +```python +>>> post.publish() +``` + +Maintenant, essayez d'obtenir à nouveau la liste des posts publiés (appuyez trois fois sur la flèche du haut, puis `entrée`) : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +]> +``` + +### Classer les objets + +Les QuerySets permettent aussi de trier la liste des objets. Essayons de les trier par le champs `created_date` : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('created_date') +, , , ]> +``` + +On peut aussi inverser l'ordre de tri en ajouter `-` au début : + +{% filename %}command-line{% endfilename %} + +```python +>>> Post.objects.order_by('-created_date') +, , , ]> +``` + +### Requêtes complexes grâce au chaînage des méthodes + +Comme vous l'avez vu, quand on applique certaines méthodes à `Post.objects` on obtient un QuerySet en résultat. Les mêmes méthodes peuvent également être appliquées sur un QuerySet, ce qui ensuite donnera lieu à un nouveau QuerySet. Ainsi, vous pouvez combiner leur effet en les **enchaînant** l'une après l'autre : + +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +, , , ]> +``` + +C'est un outil très puissant qui va vous permettre d'écrire des requêtes complexes. + +Génial ! Vous êtes maintenant prête à passer à l'étape suivante ! Pour fermer le shell, tapez ceci: + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` \ No newline at end of file diff --git a/fr-FR/django_start_project/README.md b/fr-FR/django_start_project/README.md new file mode 100644 index 00000000000..bd676dddd0a --- /dev/null +++ b/fr-FR/django_start_project/README.md @@ -0,0 +1,260 @@ +# Votre premier projet Django ! + +> Une partie de ce chapitre s’inspire du tutoriel des Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Des morceaux de ce chapitre sont inspirés du [tutoriel django-marcador](http://django-marcador.keimlink.de/), disponible sous licence Creative Commons Attribution-ShareAlike 4.0 International. Le tutoriel django-marcador a été créé par Markus Zapke-Gründemann et al. + +Nous allons créer un petit blog ! + +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 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. + +> 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. + + + +Retournons à la création de notre premier projet. Tapez la commande suivant dans votre console MacOS ou Linux. **N'oubliez pas le point `.`à la fin !** + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> 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 la commande précédente dans votre console, vous ne devez recopier que la partie qui commence par `django-admin`. La partie `(myvenv) ~/djangogirls$` montrée ici n'est qu'un exemple pour vous rappeler de taper la commande dans votre console. + + + + + +Sur Windows, vous devez taper la commander suivante. ** (N'oubliez pas le point `.` à la fin) ** : + +{% filename %}command-line{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> 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 la commande précédente dans votre console, vous ne devez recopier que la partie qui commence par `django-admin.exe`. La partie `(myvenv) C:\Users\Name\djangogirls>` montrée ici n'est qu'un exemple pour vous rappeler de taper la commande 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 + ├── mysite + │   ├── __init__.py + │   ├── settings.py + │   ├── urls.py + │   └── wsgi.py + ├── myvenv + │   └── ... + └── requirements.txt + + +> **Note** : dans votre structure de dossier, vous pourrez voir également le répertoire `venv` que nous avons créé avant. + +`manage.py` est un script qui aide à gérer ou maintenir le site. Entre autres, 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 patterns d'urls utilisés par `urlresolver`. + +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. + +**Note** : Gardez à l’esprit que `settings.py` est un fichier ordinaire, comme les autres. Vous pouvez l’ouvrir depuis l’éditeur de code, en cliquant sur « file-> open » dans le menu. Cela devrait ouvrir la fenêtre habituelle de navigation, où vous allez pouvoir chercher votre fichier `settings.py` et le sélectionner. Autrement, vous pouvez naviguer jusqu’au dossier djangogirls sur votre bureau et faire un clic droit sur le nom du fichier. Sélectionnez ensuite votre éditeur de code dans la liste qui s'affiche. Sélectionner l’éditeur est important car vous pourriez avoir d’autres programmes installés qui peuvent ouvrir le fichier, mais qui ne vous permettraient pas de le modifier. + +Ça serait sympa d'avoir l'heure correcte sur notre site Web. Allez sur la [liste Wikipedia des fuseaux horaires](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) et copiez votre fuseau horaire (TZ) (par exemple `Europe/Berlin`). + +Dans `settings.py`, recherchez la ligne qui contient `TIME_ZONE` et modifiez-la pour choisir votre propre fuseau horaire. Par exemple : + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +Un code de langue se compose de la langue, par exemple `en` pour l’anglais ou `de` pour l’allemand et du code du pays, p. ex. `de` pour l’Allemagne ou `ch` pour la Suisse. Si l’anglais n’est pas votre langue maternelle, vous pouvez ajouter votre code de langue afin que les boutons par défaut et les notifications de Django soient traduits. Vous auriez alors le bouton « Cancel » traduits dans la langue que vous avez définie. [Django est livré avec un grand nombre de traductions disponibles](https://docs.djangoproject.com/en/2.2/ref/settings/#language-code). + +Si vous voulez changer la langue, modifiez le code de langue comme montré dans la ligne suivante : + +{% filename %}mysite/settings.py{% endfilename %} + +```python +LANGUAGE_CODE = 'de-ch' +``` + +Nous allons avoir besoin aussi d'un chemin d’accès pour les fichiers statiques. (Nous allons découvrir les fichiers statiques et CSS plus tard dans le tutoriel) Allez à la *fin* du fichier et juste en dessous de `STATIC_URL`, ajoutez une nouvelle entrée `STATIC_ROOT` : + +{% filename %}mysite/settings.py{% endfilename %} + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +Lorsque `DEBUG` a valeur `True` et `ALLOWED_HOSTS` est vide, les noms d'hôte acceptés sont `[« localhost », '127.0.0.1 », ' [ :: 1]']`. Notre nom d’hôte sur PythonAnywhere ne sera donc pas accepté une fois que notre application sera déployée. Pour éviter cela, nous allons changer le paramètre suivant : + +{% filename %}mysite/settings.py{% endfilename %} + +```python +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +``` + +> **Note** : Si vous utilisez un Chromebook, ajoutez cette ligne à la fin de votre fichier settings.py : `MESSAGE_STORAGE = « django.contrib.messages.storage.session.SessionStorage »` +> +> Ajoutez `.amazonaws.com` à `ALLOWED_HOSTS` si vous utilisez cloud9 +> +> Si vous hébergez votre projet sur `Glitch.com`, nous devons protéger la clé secrète Django qui doit rester confidentielle (sinon, toute personne remixant votre projet pourrait la voir) : +> +> - Tout d'abord, nous allons créer une clé secrète aléatoire. Ouvrez à nouveau le terminal Glitch et tapez la commande suivante : +> +> {% filename %}Terminal{% endfilename %} +> +> ```bash +> python -c 'from django.core.management.utils import get_random_secret_key; \ +> print(get_random_secret_key())' +> ``` +> +> Ceci devrait afficher une longue chaîne de caractères aléatoire, parfaite à utiliser comme clé secrète pour votre tout nouveau site web Django. Nous allons maintenant coller cette clé dans un `.env` que Glitch ne vous montrera que si vous êtes propriétaire du site Web. +> +> - Créez un fichier `.env` à la racine de votre projet et ajoutez-y la propriété suivante : +> +> {% filename %}.env{% endfilename %} +> +> ```bash +> # Ici, à l'intérieur des apostrophes, vous pouvez copier et coller la clé aléatoire générée ci-dessus +> SECRET='3!0k#7ds5mp^-x$lqs2%le6v97h#@xopab&oj5y7d=hxe511jl' +> ``` +> +> - Puis mettez à jour le fichier de configuration de Django pour injecter cette valeur secrète et définir le nom du site web Django : +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> SECRET_KEY = os.getenv('SECRET') +> ``` +> +> - Et un peu plus loin, dans le même fichier, nous injectons le nom de votre nouveau site Glitch : +> +> {% filename %}mysite/settings.py{% endfilename %} +> +> ```python +> ALLOWED_HOSTS = [os.getenv('PROJECT_DOMAIN') + ".glitch.me"] +> ``` +> +> `PROJECT_DOMAIN` est générée automatiquement par Glitch. Elle contient le nom de votre projet. + +## Configuration de la base de données + +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 cette partie de votre fichier `mysite/settings.py`: + +{% filename %}mysite/settings.py{% endfilename %} + +```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 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: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: auth, admin, contenttypes, sessions + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying auth.0009_alter_user_last_name_max_length... OK + Applying sessions.0001_initial... OK + + +Et voilà ! Il ne reste plus qu'à lancer le serveur et voir si notre site web fonctionne ! + +## Lancer le serveur web + +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`: + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Si vous avez un Chromebook, utilisez plutôt la commande suivante : + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + + +ou celle-ci si vous utilisez Glitch : + +{% filename %}Glitch.com terminal{% endfilename %} + + $ refresh + + + +Si vous utilisez Windows et que vous obtenez l'erreur `UnicodeDecodeError`, tapez plutôt cette commande : + +{% filename %}command-line{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Ensuite, vous allez 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 : + +{% filename %}navigateur{% endfilename %} + + http://127.0.0.1:8000/ + + +Si vous utilisez un Chromebook et Cloud9, cliquez plutôt sur l’URL dans la fenêtre pop-up qui devrait figurer dans le coin supérieur droit de la fenêtre de commande où le serveur web est en cours d’exécution. L'URL ressemblera à quelque chose comme : + +{% filename %}navigateur{% endfilename %} + + https://.vfs.cloud9.us-west-2.amazonaws.com + + +ou sur Glitch : + + https://nom-de-votre-projet-glitch.glitch.me + + +Bravo ! Vous venez de créer votre premier site web, et de le lancer avec un serveur web ! C'est génial, non? + +![L'installation a fonctionné !](images/install_worked.png) + +Notez qu’une fenêtre de commande ne peut exécuter qu’une chose à la fois, et la fenêtre de commande que vous avez ouverte précédemment est en train d'exécuter le serveur web. Tant que le serveur web est en cours d’exécution et en attente de requêtes entrantes, le terminal acceptera du nouveau texte mais ne l'exécutera pas. + +> Nous avons vu le fonctionnement des serveurs web dans le chapitre **Comment fonctionne Internet**. + +Pour taper et executer des nouvelles commandes pendant que le serveur web est en fonction, ouvrez une nouvelle fenêtre dans votre terminal et activez votre virtualenv. Pour révoir comment ouvrir une nouvelle fenêtre, rendez-vous au chapitre [Introduction à la ligne de commande](../intro_to_command_line/README.md). Pour arrêter votre serveur web, retournez dans la fenêtre où il tourne et appuyez sur CTRL+C : gardez les boutons Control et C appuyés en même temps. (Sous Windows, vous devrez peut-être appuyer sur CTRL+Arrêt défil.) + +Prêtes pour la suite ? Il est temps de créer du contenu ! \ No newline at end of file diff --git a/fr-FR/django_templates/README.md b/fr-FR/django_templates/README.md new file mode 100644 index 00000000000..8bb92d9e643 --- /dev/null +++ b/fr-FR/django_templates/README.md @@ -0,0 +1,108 @@ +# Templates Django + +Il est temps d'afficher des données ! Pour nous aider, Django fournit des balises de gabarit (**template tags**) qui sont intégrées au framework. Pour le reste du tutoriel, nous utiliserons plutôt le mot template, bien plus répandu que sa traduction "gabarit". + +## Qu'est-ce que c'est que des balises de template ? + +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 transferer des choses ressemblant à du Python dans du HTML afin de nous permettre de construire des sites web plus rapidement. 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 utiliserons des doubles accolades avec le nom de la variable à l'intérieur. Ça ressemble à ceci : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{{ posts }} +``` + +Essayez de faire la même chose avec votre template `blog/templates/blog/post_list.html`. Ouvrez-le avec votre éditeur et 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](images/step1.png) + +Comme vous pouvez le voir, tout ce que nous avons, c'est ceci : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +, ]> +``` + +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 : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Essayez ceci dans votre template. + +![Figure 13.2](images/step2.png) + +Ça marche ! Cependant, nous aimerions plutôt afficher les posts à 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 : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +
+

Django Girls Blog

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

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% 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](images/step3.png) + +Avez-vous remarqué que nous avons utilisé une notation légèrement différente cette fois-ci (`{{ post.title }}` ou `{{ post.text }}`) ? Nous accédons aux données associées à chaque champ défini dans notre modèle `Post`. De même, le `|linebreaksbr` nous permet de rediriger le texte des posts à travers un filtre qui convertit automatiquement les fins de lignes en paragraphes. + +## Une dernière 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… + +* En premier lieu, envoyez votre code sur GitHub (push) + +{% filename %}command-line{% endfilename %} + + $ git status + [...] + $ git add . + $ git status + [...] + $ git commit -m "Modification des templates to afficher les posts contenus dans la base de données." + [...] + $ git push + + +* Ensuite, reconnectez-vous à [PythonAnywhere](https://www.pythonanywhere.com/consoles/) et allez sur la "**Bash console**" (ou démarrer-en une nouvelle), et lancez les commandes suivantes : + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd .pythonanywhere.com + $ git pull + [...] + + +(N’oubliez pas de remplacer `` avec votre propre nom de sous domaine sur PythonAnywhere, sans les chevrons.) + +* Pour finir, n'oubliez pas de recharger votre application web : onglet [Web](https://www.pythonanywhere.com/web_app_setup/) puis cliquez sur le bouton **Reload**. (Pour rejoindre les autres pages de PythonAnywhere à partir de la console, utilisez le bouton de menu dans le coin supérieur droit). Votre mise à jour devrait apparaître sur https://subdomain.pythonanywhere.com--Allez regarder dans le navigateur ! Si les posts sur PythonAnywhere ne correspondent pas à ceux qui apparaissent dans votre version locale du blog, ne vous inquiétez pas. Les deux bases de données, la locale et celle sur PythonAnywhere, ne sont pas synchronisées comme le reste des fichiers. + +Félicitations ! Maintenant, allez de l'avant et essayez d'ajouter un nouveau message dans votre administrateur Django (rappelez-vous d'ajouter publication_date!) Assurez-vous que vous êtes dans l'administrateur Django pour votre site pythonanywhere, https://subdomain.pythonanywhere.com/admin. Ensuite, rafraîchissez votre page pour voir si le message apparaît. + +Ça a marché ? Nous sommes super fière de vous ! Éloignez vous un peu de votre clavier maintenant : vous avez mérité de faire une pause. :) + +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/fr-FR/django_urls/README.md b/fr-FR/django_urls/README.md new file mode 100644 index 00000000000..2acb1af708e --- /dev/null +++ b/fr-FR/django_urls/README.md @@ -0,0 +1,103 @@ +# Les URL de Django + +Nous sommes sur le point de créer notre première page web : une page d'accueil pour votre blog ! Mais d'abord, commençons par en apprendre un peu plus sur les URL de Django. + +## Qu'est-ce qu'une URL ? + +Une URL est une adresse web. Vous pouvez voir une URL chaque fois que vous visitez un site web. Elle est visible dans la barre d'adresse de votre navigateur. (Oui ! `127.0.0.1:8000` est aussi une URL ! Et `https://djangogirls.org` est aussi une URL.) + +![URL](images/url.png) + +Chaque page internet a besoin de sa propre URL. C'est grâce à cela que votre application sait ce qu'elle doit afficher à un utilisateur qui ouvre cette URL. Dans Django, nous utilisons un outil appelé `URLconf` (Configuration d'URL). URLconf est un ensemble de modèles que Django va essayé de faire correspondre à l'URL demandée afin de trouver la vue adaptée. + +## Comment les URLs fonctionnent-elles dans Django ? + +Ouvrons le fichier `mysite/urls.py` dans notre éditeur de code et regardons à quoi il ressemble : + +{% filename %}mysite/urls.py{% endfilename %} + +```python +"""mysite URL Configuration + +[...] +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +``` + +Comme vous pouvez le voir ici, Django a déjà préparé quelque chose pour nous. + +Les lignes entre triples guillemets (`'''` or `"""`) sont appelées docstrings. Vous pouvez les écrire en haut d'un fichier, d'une classe ou d'une méthode pour décrire son fonctionnement. Elle ne seront pas exécutées par Python. + +L'URL admin, que vous avez abordé dans le chapitre précédent est déjà là : + +{% filename %}mysite/urls.py{% endfilename %} + +```python + path('admin/', admin.site.urls), +``` + +Cette ligne signifie que pour toutes les URL commençant par `admin/`, Django trouvera une *vue* correspondante. Dans cet exemple, nous incluons de nombreuses URL admin. Elles ne sont donc pas toutes contenues dans ce petit fichier. C'est plus lisible et plus propre. + +## Votre première URL Django ! + +Il est temps de créer notre première URL ! Nous voulons que 'http://127.0.0.1:8000/' soit la page d'accueil de notre blog et qu'elle affiche la liste des articles. + +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`. + +Allez-y ! Ajoutez une ligne qui importera `blog.urls`. Vous devrez également modifier la ligne ` from django.urls...` car nous utiliseront la fonction `include`. Il vous faudra ajouter cet import à la ligne. + +Votre fichier `mysite/urls.py` devrait maintenant ressembler à ceci : + +{% filename %}mysite/urls.py{% endfilename %} + +```python +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', 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. + +## blog.urls + +Créez un nouveau fichier vide nommé `urls.py` dans le répertoire `blog`, et ouvrez-le dans l'éditeur de code. Très bien ! Ajoutez ces deux premières lignes : + +{% filename %}blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views +``` + +Nous venons d'importer la fonction `path` de Django 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 !) + +Après ça, nous pouvons ajouter notre premier modèle (pattern) d'URL: + +{% filename %}blog/urls.py{% endfilename %} + +```python +urlpatterns = [ + path('', views.post_list, name='post_list'), +] +``` + +Comme vous pouvez le voir, nous assignons une `vue` appelée `post_list` à l'URL racine. Ce modèle d’URL correspond à une chaîne vide et le résolveur d'URL de Django ignore le nom de domaine (par exemple, http://127.0.0.1:8000/), soit la première 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/". + +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 nom d'URLs simple à retenir. + +Si vous essayez d'aller sur http://127.0.0.1:8000/ maintenant, vous trouverez un message du style « page web non disponible ». C’est parce que le serveur (vous vous souvenez d'avoir tapé `runserver` ?) n'est plus en exécution. Jetez un oeil à la console pour savoir pourquoi. + +![Erreur](images/error1.png) + +Votre console affiche une erreur, mais ne vous inquiétez pas – c’est en fait très utile : elle vous dit qu’il n’existe aucun attribut « post_list » (**no attribute 'post_list'**). C’est le nom de la *vue* que Django essaie de trouver et d’utiliser, or nous ne l'avons pas encore créée. À ce stade, votre `/admin/` ne fonctionnera pas non plus. Pas de problème, on y vient. Si vous voyez un message d’erreur différent, essayez de redémarrer votre serveur web. Pour faire cela, dans la console qui exécute le serveur web, arrêtez-le en appuyant sur CTRL+C (les touches Control et C simultanément). Sous Windows, vous devrez peut-être appuyer sur Ctrl+Break. Vous devrez alors redémarrer le serveur web en exécutant la commande `python manage.py runserver`. + +> 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/2.2/topics/http/urls/ \ No newline at end of file diff --git a/fr-FR/django_views/README.md b/fr-FR/django_views/README.md new file mode 100644 index 00000000000..530a34f1b35 --- /dev/null +++ b/fr-FR/django_views/README.md @@ -0,0 +1,44 @@ +# Vues Django - C'est l'heure de créer ! + +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`. Nous allons créer ce template dans le chapitre suivant. Concrètement, les vues ne sont que des fonctions Python un peu plus élaborées que celles que nous avons créé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`. + +## blog/views.py + +Ok, allons-y ! Ouvrons ce fichier dans notre éditeur de code pour voir ce qu'il contient : + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Pas beaucoup de choses pour l'instant. + +N’oubliez pas que les lignes commençant par `#` sont des commentaires, ce qui signifie qu'elles ne sont pas exécutées par Python. + +Nous allons créer une *vue* comme l’indique le commentaire. Ajoutez la vue minimale suivante : + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Comme vous pouvez le voir, nous avons créé une fonction (`def`) appelée `post_list` qui prend une `request (requête)` et qui va `return (retourner)` la valeur donnée par une autre fonction `render` qui va assembler 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. + +Une autre erreur ! Voyons ce qu'elle nous dit : + +![Erreur](images/error.png) + +Cela indique que le serveur tourne, ce qui est bien, mais il y a quelque chose qui ne va pas, non ? Ne vous inquiétez pas, c’est juste une page d’erreur, il ne faut pas avoir peur d'elle ! Au contraire, tout comme les messages d’erreur dans la console, elle nous est très utile. Vous pouvez lire que *TemplateDoesNotExist*. Nous allons corriger ce bug et créer un modèle (template) dans le prochain chapitre ! + +> Pour en apprendre un peu plus sur les vues dans Django, consultez la documentation officielle : https://docs.djangoproject.com/en/2.2/topics/http/views/ \ No newline at end of file diff --git a/fr-FR/dynamic_data_in_templates/README.md b/fr-FR/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..4c25163a082 --- /dev/null +++ b/fr-FR/dynamic_data_in_templates/README.md @@ -0,0 +1,84 @@ +# 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. + +C'est à ça que servent les *vues* : connecter les modèles et les templates. Dans notre *vue* `post_list`, nous allons avoir besoin de prendre les modèles dont nous avons besoin et de les passer au template. C'est dans la *vue* que nous allons décider ce qui va s'afficher (quel modèle) dans un template. + +Ok, et sinon, on fait comment ? + +Nous allons avoir besoin d'ouvrir le fichier `blog/views.py` dans l'éditeur de code. Pour l'instant, la *vue* `post_list` ressemble à ceci : + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +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 : + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render +from .models import Post +``` + +Le point avant `models` signifie *dossier courant* ou *application courante*. Les fichiers `views.py` et `models.py` sont dans le même répertoire. Cela signifie que nous pouvons utiliser `.` suivi par le nom du fichier (sans `.py`). Ensuite, nous importons le modèle (`Post`). + +Ok, et après ? Afin de pouvoir aller chercher les véritables posts de blog de notre modèle `Post`, nous avons besoin de quelque chose qui s'appelle un `QuerySet`. + +## QuerySet + +Normalement, ce mot doit vous évoquer quelque chose. Nous en avons un peu parlé dans la section [Django ORM (QuerySets)](../django_orm/README.md). + +Maintenant, nous allons nous intéresser à comment publier les post classés par date de publication (`published_date`). Ça tombe bien, on a déjà fait ça dans la section sur les QuerySets ! + +{% filename %}blog/views.py{% endfilename %} + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Ouvrons donc le fichier `blog/views.py` dans l’éditeur de code et ajoutons le morceau de code suivant à la fonction `def post_list(request)`. N’oubliez pas d’ajouter d’abord `from django.utils import timezone`. + +{% filename %}blog/views.py{% endfilename %} + +```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', {}) +``` + +Pour afficher notre QuerySet sur la liste des publications de notre blog, il nous reste deux choses à faire: + +1. Passer les `posts` QuerySet dans le contexte du modèle, en changeant l'appel à la fonction `render` . Nous allons le faire maintenant. +2. Modifier le modèle pour afficher le QuerySet `posts` . Nous en parlerons dans un chapitre ultérieur. + +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. + +Dans la fonction `render`, nous avons un paramètre `request`, qui désigne tout ce que nous recevons d'un utilisateur par l'intermédiaire d'Internet, et un autre qui signale le fichier template (`'blog/post_list.html'`). Le dernier paramètre, `{}`, va nous permettre de glisser des informations que notre template va utiliser. Nous devons donner des noms à ces informations (nous allons rester sur `'posts'` pour le moment). :) Ça va ressembler à ça : `{'posts': posts}`. La partie située avant `:` est une chaine de caractères ; vous devez donc l'entourer de guillemets : `''`. + +Au final, notre fichier `blog/views.py` doit ressembler à ceci maintenant : + +{% filename %}blog/views.py{% endfilename %} + +```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/2.2/ref/models/querysets/ \ No newline at end of file diff --git a/fr-FR/extend_your_application/README.md b/fr-FR/extend_your_application/README.md new file mode 100644 index 00000000000..56e9c2d1b6a --- /dev/null +++ b/fr-FR/extend_your_application/README.md @@ -0,0 +1,214 @@ +{% set warning_icon = '' %} + +# Finaliser votre application + +Nous avons déjà franchi toutes les étapes nécessaires à la création de notre site web : nous savons maintenant comment écrire un modèle, une URL, une vue et un template. Nous avons même réussi à rendre notre site web plus joli . + +C'est le moment de pratiquer tout ce que vous avez appris ! + +Tout d'abord, il faudrait que notre blog possède une page qui permet d'afficher un post, n'est-ce pas ? + +Nous avons déjà un modèle `Post`, nous n'avons donc pas besoin d'ajouter quoi que ce soit à `models.py`. + +## Créer un lien dans un template + +Nous allons tout d'abord ajouter un lien à l'intérieur du fichier `blog/templates/blog/post_list.html`. Ouvrez-le dans l’éditeur de code et voyez qu'il devrait ressembler à ceci : {% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +{% 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 %} + +{% filename %}{{ warning_icon }} blog/templates/blog/post_list.html{% endfilename %} + +```html +

{{ post.title }}

+``` + +{% 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-ci, nous allons utiliser des balises qui vont s'occuper de créer des URLs à notre place !{% endraw %} + +La partie `post_detail` signifie que Django s'attend de trouver une URL en `blog/urls.py` avec nom = post_detail + +Et qu’en est-il de `pk=post.pk` ? `pk` est l’abréviation de clé primaire (« primary key » en anglais), qui est un identifiant unique pour chaque entrée dans une base de données. Chaque modèle Django a un champ qui sert de clé primaire, et peu importe son autre nom, il peut aussi être appelé par le nom « pk ». Comme nous n’avons pas spécifié de clé primaire dans notre modèle `Post`, Django en crée une pour nous (par défaut, un champ nommé « id » contenant un nombre qui augmente pour chaque entrée, c’est-à-dire 1, 2, 3, etc.) et l’ajoute comme champ à chacun de nos posts. Nous accédons à la clé primaire en écrivant `post.pk`, pareil que pour accéder aux autres champs (`title`, `author`, etc.) de notre objet `Post` ! + +Maintenant si nous jetons un coup d’œil à http://127.0.0.1:8000/, nous rencontrons une erreur. Ceci est prévisible, puisque nous n'avons ni d'URL ni de *view* pour `post_detail`. L'erreur ressemble à ceci : + +![Erreur NoReverseMatch](images/no_reverse_match2.png) + +## Créer une URL vers le contenu d'un post + +Allons créer notre URL dans le fichier `urls.py` pour notre *vue* `post_detail` ! + +Nous aimerions que le contenu de notre premier post s'affiche à cette **URL** : http://127.0.0.1:8000/post/1/ + +Allons créer une URL dans le fichier `blog/urls.py` qui dirigera Django vers une *vue* appelée `post_detail`. Cela nous permettra d'afficher l'intégralité d'un post de blog. Ouvrez le fichier `blog/urls.py` dans l’éditeur de code et ajoutez la ligne `path('post//', views.post_detail, name='post_detail'),` afin que le fichier ressemble à ceci : + +{% filename %}{{ warning_icon }} blog/urls.py{% endfilename %} + +```python +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.post_list, name='post_list'), + path('post//', views.post_detail, name='post_detail'), +] +``` + +La partie `post//` spécifie un modèle d’URL – allons voir plus dans le détail : + +- `post/` signifie que l’URL doit commencer par le mot **post** suivie d’un **/**. OK, pas très compliqué. +- ``– cette partie est plus délicate. Cela signifie que Django s’attend à une valeur entière (int), qu'en suite il transférera à une vue comme variable de nom `pk`. +- `/` – il nous faut un **/** à nouveau avant la fin de l’URL. + +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 à cette *vue* que `pk` est égal à `5`. + +OK, nous avons ajouté un nouveau modèle d’URL à `blog/urls.py` ! Actualisons la page : http://127.0.0.1:8000/ Boom ! Le serveur a cessé de marcher à nouveau. Jetez un oeil sur la console – comme prévu, il y a encore une autre erreur ! + +![AttributeError](images/attribute_error2.png) + +Vous souvenez-vous de ce qu'il faut faire ensuite ? Il faut ajouter une vue ! + +## Ajouter une vue pour le contenu du post + +Cette fois-ci, nous allons donner un paramètre supplémentaire à notre *vue* : `pk`. Notre *vue* va avoir besoin de le récupérer, n'est ce pas ? Pour cela, nous allons définir une fonction : `def post_detail(request, pk):`. Notez que ce paramètre doit avoir exactement le même nom que celui que nous avons spécifié dans le fichier `urls` (`pk`). Notez aussi qu’oublier de mettre cette variable est incorrect et produira une erreur ! + +Maintenant, nous aimerions obtenir qu'un seul blog post. Pour cela, nous allons utiliser des QuerySets qui ressemblent à ceux-ci: + +{% filename %}{{ warning_icon }} blog/views.py{% endfilename %} + +```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! + +![Erreur DoesNotExist](images/does_not_exist2.png) + +Dans l'idéal, nous aimerions pouvoir éviter ça! Encore une fois, 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](images/404_2.png) + +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`! + +Dans le fichier `blog/urls.py` nous avons crée un modèle d'URL `post_detail` qui fait référence à la vue `views.post_detail`. En conséquence, Django s'attend à qu'une fonction `post_detail` soit définie dans le fichier `blog/views.py`. + +Ouvrez maintenant le fichier `blog/views.py` dans l'éditeur de code et ajoutez la ligne suivante après les autres lignes du type `from` qui existent déjà : + +{% filename %}blog/views.py{% endfilename %} + +```python +from django.shortcuts import render, get_object_or_404 +``` + +A la fin du fichier nous ajoutons finalement notre *view* : + +{% filename %}blog/views.py{% endfilename %} + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Hop, réactualisons la page http://127.0.0.1:8000/ + +![Vue post_list](images/post_list2.png) + +C'est bon, ça a marché ! Mais que ce passe-t-il lorsque nous cliquons sur un lien dans un titre de blog post ? + +![Erreur TemplateDoesNotExist](images/template_does_not_exist2.png) + +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` et nous l'ouvrons ensuite avec notre éditeur de code. + +Entrez le code suivant : + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} + + {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +Une nouvelle fois, nous faisons hériter de `base.html`. Dans le `content` block, nous voulons afficher 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. (Vous souvenez-vous de `if ... else ..` que nous avons appris dans le chapitre **Introduction à Python** ?) Dans ce cas spécifique, nous voulons vérifier que `published_date` existe.{% endraw %} + +Ok, vous pouvez maintenant actualiser votre page et voir si `TemplateDoesNotExist` a enfin disparu. + +![Page détaillée d'un post](images/post_detail2.png) + +Yay ! Ça marche! + +# C'est le moment de deployer ! + +Ce serait bien de mettre à jour la version de notre site sur PythonAnywhere. On s'accroche et on déploie encore une fois :) + +{% filename %}command-line{% endfilename %} + + $ git status + $ git add . + $ git status + $ git commit -m "Ajout de la vue et du template de détail blog post ainsi que du CSS pour le site." + $ git push + + +Puis, dans la console bash de [PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +(N’oubliez pas de remplacer `` avec votre propre sous-domaine PythonAnywhere, sans les chevrons.) + +## Mise à jour des fichiers statiques sur le serveur + +Des serveurs comme PythonAnywhere réservent un traitement particuliers aux "fichiers statiques" (par exemple les fichiers CSS), notamment afin de les charger plus rapidement. En conséquence, à chaque fois que nos fichiers CSS changent, nous devons executer une commande pour que le serveur les mette à jour. Cette commande s'appelle `collectstatic`. + +Démarrez en activant votre virtualenv, s'il n'est pas toujours actif (PythonAnywhere propose la commande `workon`, ce qui est l'équivalent de `source myenv/bin/activate` sur votre ordinateur) : + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ workon .pythonanywhere.com + (ola.pythonanywhere.com)$ python manage.py collectstatic + [...] + + +La commande `manage.py collectstatic` nous rappelle un peu `manage.py migrate`. Nous apportons des changements à notre code, puis nous disons à Django *d'appliquer* ces changements, que ce soit pour la gestion des fichiers statiques ou pour la structure de la base de données. + +Maintenant nous sommes prêtes à aller sur [« Web »](https://www.pythonanywhere.com/web_app_setup/) (depuis le menu en haut à droite de la console), appuyer sur **Reload** et voir les résultats à votre adresse https://sous-domaine.pythonanywhere.com. + +Normalement, ça devrait suffire ! Encore bravo! :) \ No newline at end of file diff --git a/fr-FR/how_the_internet_works/README.md b/fr-FR/how_the_internet_works/README.md new file mode 100644 index 00000000000..214707e0954 --- /dev/null +++ b/fr-FR/how_the_internet_works/README.md @@ -0,0 +1,47 @@ +# Comment fonctionne Internet + +> Pour les lectrices autodidactes : ce chapitre est traité dans la vidéo [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc). +> +> Ce chapitre s’inspire de la conférence « Comment fonctionne Internet » de Jessica McKellar (http://web.mit.edu/jesstess/www/). + +Vous utilisez sûrement Internet tous les jours. Mais savez-vous ce qui ce passe vraiment quand vous tapez une adresse comme https://djangogirls.org dans votre navigateur et appuyez sur `Entrée`? + +La première chose que vous devez comprendre c’est qu’un site Web consiste en un tas de fichiers sauvegardés sur un disque dur -- tout comme vos films, musiques ou 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é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. + +Bon, d'accord. Mais vous avez envie de savoir à quoi Internet ressemble, n'est-ce-pas ? + +Nous vous avons fait un dessin ! Voilà à quoi ça ressemble : + +![Figure 1.1](images/internet_1.png) + +C'est le bazar, non ? En fait, c'est un réseau de machines connectées entre elles (les *serveurs* dont on parlait plus tôt). Des centaines de milliers de machines ! Des millions de kilomètres de câbles, partout dans le monde ! Vous pouvez aller voir une carte des câbles sous-marins (http://submarinecablemap.com/) pour voir à quel point le réseau est compliqué. Voici une capture d'écran du site : + +![Figure 1.2](images/internet_3.png) + +Fascinant, non ? Cependant, il n'est 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 : + +![Figure 1.3](images/internet_2.png) + +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 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](images/internet_4.png) + +Cela fonctionne comme ça - vous envoyez des messages et attendez une réponse. Vous utilisez des octets de données à la place du papier et du crayon, 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ù 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 : une adresse, un timbre, etc. 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/0> (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 parlé, il est temps de commencer à créer des trucs ! \ No newline at end of file diff --git a/fr-FR/html/README.md b/fr-FR/html/README.md new file mode 100644 index 00000000000..e810b99b45e --- /dev/null +++ b/fr-FR/html/README.md @@ -0,0 +1,227 @@ +# Introduction au HTML + +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 fonctionne l'Internet**). + +## Qu'est-ce que le HTML ? + +HTML est un code qui est interprété par votre navigateur (Chrome, Firefox ou Safari) et qui permet d'afficher une page web à l'utilisateur. + +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 ! + +Créer un template signifie créer un fichier template. Et oui, encore des fichiers ! Vous aviez déjà probablement remarqué que tout tourne autour des fichiers. + +Les templates sont sauvegardés dans le dossier `blog/templates/blog`. Tout d'abord, créons un dossier appelé `templates` à l'intérieur du dossier de notre blog. Ensuite, créez un autre dossier appelé `blog` à l'intérieur de votre dossier templates : + + 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 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`. + +Allons regarder à quoi ressemble notre site maintenant : http://127.0.0.1:8000/ + +> Si vous avez encore l'erreur `TemplateDoesNotExist`, essayez de redémarrer votre serveur. Allez sur votre ligne de commande et arrêtez votre server 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](images/step1.png) + +Et voilà, il n'y a plus d'erreurs ! Bravo :) Cependant, notre site ne peut rien faire d'autre pour le moment qu'afficher une page blanche. La faute à notre template que nous avons laissé vide. Allons corriger ça. + +Ouvrez le nouveau fichier dans l’éditeur de code et ajoutez le morceau suivant : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + +

Bonjour !

+

Ça marche !

+ + +``` + +Alors, à quoi ressemble notre site web maintenant ? Allons le découvrir : http://127.0.0.1:8000/ + +![Figure 11.2](images/step3.png) + +Ça marche ! Bon boulot! :) + +* La ligne `` n'est pas une balise HTML. Elle ne déclare que le type de document. Ici, elle informe le navigateur web que le type de document est [HTML5](https://html.spec.whatwg.org/#the-doctype). C'est toujours ainsi que débute un fichier HTML5. +* La balise la plus élémentaire, ``, figure toujours au début de n'importe quelle page web tandis que `` est toujours située à la fin. Comme vous pouvez le constater, l'intégralité du contenu de notre page web est située entre la balise de départ, ``, et la balise de fin, `` +* `

` est la balise pour les éléments de type paragraphe. `

` permet de fermer chaque paragraphe. + +## Head et Body + +Chaque page HTML est divisée en deux éléments : **head** (entête) et **body** (corps. + +* **head** est un élément qui contient des informations sur le document : son contenu ne s'affichera pas à l'écran. + +* **body** est un élément qui contient tout le reste. Son contenu s'affichera à l'écran et constituera notre page web. + +Nous utilisons `` pour transmettre la configuration de la page au navigateur tandis que `` l'informe sur le contenu de la page. + +Par exemple, vous pouvez donner un titre à votre page web en utilisant l'élément titre dans le `` : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Ola's blog + + +

Bonjour !

+

Ça marche !

+ + +``` + +Sauvegardez votre fichier et actualisez la page. + +![Figure 11.3](images/step4.png) + +Vous avez vu comment le navigateur a compris que « Le Blog d'Ola » est le titre de votre page ? Il a interprété `Le blog d'Ola` et a placé ce texte dans la barre de titre de votre navigateur (c'est ce titre qui va être aussi utilisé lorsque vous créez un marque-page, etc.). + +Vous avez aussi probablement remarqué que chaque balise ouvrante possède sa *balise fermante*, composée d'un `/`, est qu'elles *encadrent* les différents éléments. Cela signifie que vous ne pouvez pas fermer une balise si celles imbriquées à l'intérieur de celle-ci n'ont pas été fermées. + +Pensez à lorsque vous mettez des choses à l'intérieur de boîtes. Vous avez une grosse boîte, ``; à l'intérieur de celle-ci, on trouve une plus petite boîte, ``, qui contient elle-même d'autres petites boîtes, `

`. + +Essayez de vous rappeler de cet exemple lorsque vous utilisez les balises *fermantes* et que vous avez des éléments *imbriqués*. Si vous ne suivez pas ces règles, votre navigateur risque de ne pas être capable d'interpréter votre code correctement et votre page web sera mal affichée. + +## Personnaliser votre template + +Et si nous en profitions pour nous amuser un peu ? Essayons de personnaliser notre template ! Voici quelques balises que vous pouvez utiliser : + +* `

Titre 1

` pour vos titres les plus importants +* `

Titre 2

` pour les sous-titres +* `

Titre 3

` ... et ainsi de suite jusqu'à `
` +* `

Un paragraphe contenant du texte

` +* `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 et il n'y a pas de balise fermante) +* `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 +* `` définit un ensemble de liens de navigation +* `
` spécifie du contenu indépendant et autonome +* `
` définit une section dans un document +* `
` spécifie un en-tête pour un document ou une section +* `
` spécifie le contenu principal d'un document +* `` définit du contenu en dehors du contenu dans lequel il est placé (comme une barre latérale) +* `
` définit un pied de page pour un document ou une section +* `` définit un instant spécifique (ou un horodatage) + +Voici un exemple d’un modèle complet, copiez et collez-le dans `blog/templates/blog/post_list.html` : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html + + + + Blog Django Girls + + +
+

Blog Django Girls

+
+ +
+ +

Mon premier article

+

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.

+
+ +
+ +

Mon second article

+

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éé ici une section `en-tête` et deux sections `article`. + +* Le premier élément `header` contient le titre de notre blog - c'est à la fois un titre et un lien +* Les deux éléments `article` contiennent nos articles de blog avec une date de publication dans un élément `time` un élément `h2` avec un titre de publication qui est cliquable et un élément `p` (paragraphe) pour le texte de notre blog. + +Ce qui nous donne : + +![Figure 11.4](images/step6.png) + +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 faire maintenant, c'est d'afficher les posts que nous avons créés précédemment dans l'interface d'administration de Django. Penchons-nous là dessus. + +## Une dernière chose : déployer ! + +Ne serait-il pas génial de pouvoir voir tous ces changements en ligne ? Hop, déployons à nouveau ! + +### 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) : + +{% filename %}command-line{% endfilename %} + + $ git status + + +Assurez-vous d'être dans le dossier `djangogirls`. Voici la commande qui permet de dire à `git` d'inclure tout les changements qui ont eu lieu dans ce dossier : + +{% filename %}command-line{% endfilename %} + + $ git add . + + +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) : + +{% filename %}command-line{% endfilename %} + + $ 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. + +{% filename %}command-line{% endfilename %} + + $ git commit -m "Modification du HTML du site" + + +> **Note** Assurez-vous d'utiliser des guillemets doubles autour du message de commit. + +Une fois que nous avons fait cela, nous pouvons mettre en ligne (pusher) nos modifications sur GitHub : + +{% filename %}command-line{% endfilename %} + + $ git push + + +### Puller les modifications sur PythonAnywhere et recharger son appli web + +* Allez sur la page des [consoles de PythonAnywhere](https://www.pythonanywhere.com/consoles/). Retournez dans votre **console Bash** ou ouvrez-en une nouvelle puis tapez la commande suivante : + +{% filename %}PythonAnywhere command-line{% endfilename %} + + $ cd ~/.pythonanywhere.com + $ git pull + [...] + + +N’oubliez pas de remplacer `` avec votre propre sous-domaine PythonAnywhere, sans les chevrons. Votre nom de sous-domaine est normalement votre nom d'utilisateur PythonAnywhere, mais dans certains cas, il peut être un peu différent (par exemple si votre nom d'utilisateur contient des lettres capitales). Donc, si cette commande ne fonctionne pas, utilisez la commande `ls` (lister fichiers) pour trouver votre sous-domaine/nom de dossier, puis `cd` jusque là. + +Maintenant, vous voyez votre code en train d'être téléchargé. Si vous voulez vérifier que le nouveau code est arrivé sur PythonAnywhere, vous pouvez aller sur la page **"Files"** et y retrouver les fichiers (vous pouvez naviguer dans les différentes pages de PythonAnywhere depuis le menu). + +* Pour finir, n'oubliez pas de recharger votre application web : onglet [Web](https://www.pythonanywhere.com/web_app_setup/) puis cliquez sur le bouton **Reload**. + +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'aider à votre coach. :) \ No newline at end of file diff --git a/fr-FR/installation/README.md b/fr-FR/installation/README.md new file mode 100644 index 00000000000..052782998f5 --- /dev/null +++ b/fr-FR/installation/README.md @@ -0,0 +1,68 @@ +# 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 Internet](../how_the_internet_works/README.md). + +La raison est que toutes les informations nécessaires aux installations seront données au fur et à mesure dans les différents chapitres du tutoriel. Celle-ci est juste une page supplémentaire qui rassemble toutes les instructions d’installation en un seul endroit (ce qui est utile pour certains formats d’atelier). Vous pouvez choisir d’installer tout ce qui est sur cette page dès 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 ! + +# Si vous participez à un atelier + +Si vous participez à un [événement Django Girls](https://djangogirls.org/events/) : + +* Dans certains cas un « party d’installation » a lieu avant l’atelier principal. Si vous vous trouvez à un party d’installation, cette page est pour vous ! Suivez les instructions ici pour installer tout ce dont vous avez besoin pour l’atelier. Demandez de l'aide aux coaches si nécessaire. Ensuite, pendant l'atelier vous pourrez ignorer les instructions d’installation que vous rencontrerez dans le tutoriel. +* Les organisateurs de votre atelier vous ont peut-être proposé de procéder aux installations chez vous. Si c'est le cas, cette page est pour vous ! Suivez les instructions ici, autant que vous le pouvez. Pendant l’atelier principal, quand vous arrivez à une étape nécessitant d'un logiciel que vous n'avez pas réussi à installer toute seule, vous pourrez demander à votre coach. +* Si votre atelier n’a pas de party d'installation (ou si vous l'avez raté), et si les organisateurs ne vous ont pas demandé d’essayer de tout installer en amont, ignorez cette page et allez directement au chapitre [Comment fonctionne Internet](../how_the_internet_works/README.md). Vous allez installer tout ce dont vous avez besoin au fur et à mesure que vous avancez dans le tutoriel. + +# Installation + +Dans ce tutoriel, vous allez apprendre comment créer un blog. Le tutoriel vous guidera à travers toute les étapes d'installation des différents logiciels, ansi que de création de comptes en ligne nécessaires. Cette page regroupe l’ensemble des instructions concernant installations et comptes en ligne en un seul endroit (ce qui est utile pour certains formats d’atelier). + + {% include "/chromebook_setup/instructions.md" %} + + + +# Brève introduction à la ligne de commande {#command-line} + +Dans les étapes ci-dessous vous allez rencontrer les noms « console », « terminal », « invite de commande » ou « ligne de commande ». Tous ces termes signifient la même chose : une fenêtre sur votre ordinateur où vous pouvez rentrer des commandes. Une fois que vous aurez démarré le tutoriel principal, vous apprendrez plus sur la ligne de commande. Pour l’instant, le plus important est que vous appreniez à ouvrir un terminal et que vous voyez à quoi cela ressemble : {% include "/intro_to_command_line/open_instructions.md" %} + +# Installer Python {#python} + +{% include "/python_installation/instructions.md" %} + +# Installer un éditeur de code {#code-editor} + +{% include "/code_editor/instructions.md" %} + +# Mettre en place virtualenv et installer Django {#virtualenv} + +{% include "/django_installation/instructions.md" %} + +# Installer Git {#git} + +{% include "/deploy/install_git.md" %} + +# Créer un compte GitHub {#github-account} + +Allez sur [GitHub.com](https://www.github.com) et créez un compte d’utilisateur gratuitement. N’oubliez pas votre mot de passe (ajoutez-le à votre gestionnaire de mots de passe, si vous utilisez un). + +# Créer un compte PythonAnywhere {#pythonanywhere-account} + +{% 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 Internet](../how_the_internet_works/README.md) + +* [Introduction à la ligne de commande](../intro_to_command_line/README.md) + +* [Introduction à Python](../python_introduction/README.md) + +* [Qu'est-ce que Django?](../django/README.md) + +# Profitez de l’atelier ! + +Lors de l’atelier, vous serez en mesure d'attaquer directement le chapitre [Votre premier projet Django !](../django_start_project/README.md) parce que vous aurez déjà couvert le matériel dans les chapitres précédents. \ No newline at end of file diff --git a/fr-FR/intro_to_command_line/README.md b/fr-FR/intro_to_command_line/README.md new file mode 100644 index 00000000000..d52adf26777 --- /dev/null +++ b/fr-FR/intro_to_command_line/README.md @@ -0,0 +1,441 @@ +# Introduction à l'interface en ligne de commande + +> Pour les lectrices à la maison : ce chapitre est traité dans la vidéo [Votre nouvel ami : la ligne de commande](https://www.youtube.com/watch?v=jvZLWhkzX-8). + +C'est un peu exaltant, non ? Dans quelques instants, vous allez écrire votre première ligne de code! :) + +**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 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. 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, nous avons d'abord besoin d'ouvrir notre interface en ligne de commande. + +{% include "/intro_to_command_line/open_instructions.md" %} + +## Invite de commande + +Vous devriez maintenant voir une fenêtre noire ou blanche qui attend vos commandes. + + + +Si vous êtes sous Mac ou Linux, vous verrez probablement un `$`, comme ça : + +{% filename %}command-line{% endfilename %} + + $ + + + + + + +Si vous êtes sous Windows, vous verrez probablement un `>`, comme ça : + +{% filename %}command-line{% endfilename %} + + > + + +Jetez un coup d'œil à la section Linux ci-dessus : c'est à cela que la ligne de commande ressemblera une fois que vous serez sur PythonAnywhere. + + + +Chaque commande que vous taperez sera automatiquement précédée par un `$` ou `>` et une espace. Vous ne devez pas les rentrer vous-même, votre ordinateur le fera 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. Pas de problème : c'est parfaitement normal. + +La partie jusque et y compris le `$` ou le `>` est appelée *l’invite de commande*, ou *prompt* (en anglais) pour faire court. Elle vous invite à entrer une commande. + +Dans le tutoriel, lorsque nous voulons que vous tapiez une commande, nous allons inclure le `$` ou `>` et parfois d'autres information juste avant, à sa gauche. Ignorez cette partie à gauche et tapez uniquement la commande, qui commence après l’invite. + +## Votre première commande (YAY !) + +Commençons en tapant cette commande : + + + +{% filename %}command-line{% endfilename %} + + $ whoami + + + + + + +{% filename %}command-line{% endfilename %} + + > whoami + + + + +Puis appuyez sur la touche `entrée`. Voilà ce qui s'affiche chez moi : + +{% filename %}command-line{% endfilename %} + + $ whoami + olasitarska + + +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 à 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. Allons-y ! + +### Dossier courant + +Ce serait pratique de savoir dans quel répertoire nous nous trouvons. Pour le savoir, tapez la commande suivante et appuyez sur `entrée` : + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska + + +> Remarque : « pwd » veut dire « print working directory » (afficher le dossier courant). + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska + + +> Note : « cd » signifie « changer répertoire ». Avec PowerShell vous pouvez utiliser pwd comme sur Linux ou Mac OSX. + + + +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. + +* * * + +### En savoir plus sur une commande + +De nombreuses commandes que vous pouvez taper à l’invite de commande ont une aide intégrée que vous pouvez afficher et lire ! Par exemple, pour en savoir plus sur le répertoire actuel : + + + +macOS et Linux ont une commande `man`, qui donne des informations sur les commandes. Essayez `man pwd` et regardez ce qui s'affiche, ou ajoutez `man` devant une autre commande pour voir sa documentation. La sortie de `man` est normalement paginée. Utilisez la barre d’espace pour passer à la page suivante et `q` pour quitter l’aide. + + + + + +Ajouter un `/ ?` à la fin de la commande devrait également permettre d'afficher la page d’aide. Vous devrez peut-être faire défiler votre fenêtre de commande vers le haut pour tout voir. Essayez `cd / ?`. + + + +### Lister les fichiers et les dossiers + +Du coup, que pouvons-nous trouver dans ce dossier personnel ? Voyons voir : + + + +{% filename %}command-line{% endfilename %} + + $ ls + Applications + Bureau + Musique + Téléchargements + ... + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + Directory of C:\Users\olasitarska + 05/08/2020 07:28 PM
Applications + 05/08/2020 07:28 PM Bureau + 05/08/2020 07:28 PM Téléchargements + 05/08/2020 07:28 PM Musique + ... + + +> Remarque : Dans PowerShell, vous pouvez également utiliser "ls" comme sur Linux et Mac OS X. + +* * * + +### Changer le dossier courant + +Maintenant, essayons d'aller sur notre Bureau : + + + +{% filename %}command-line{% endfilename %} + + $ cd Bureau + + + + + + +{% filename %}command-line{% endfilename %} + + $ cd Bureau + + +Notez que le nom du répertoire « Bureau » pourrait être traduit dans la langue de votre compte Linux. Si c'est le cas, vous devrez remplacer `Bureau` par sa traduction. Par exemple, `Schreibtisch` pour l’allemand ou <0>Desktop pour l'anglais. + + + + + +{% filename %}command-line{% endfilename %} + + > cd Bureau + + + + +Vérifions que ça a bien changé : + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Bureau + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Bureau + + + + +Et voilà ! + +> 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 la touche `tabulation` deux fois pour avoir une liste des options. + +* * * + +### Créer un dossier + +Que diriez-vous de créer un répertoire dédié aux exercices sur votre bureau ? Vous pouvez le faire de cette façon : + + + +{% filename %}command-line{% endfilename %} + + $ mkdir exercices + + + + + + +{% filename %}command-line{% endfilename %} + + > mkdir exercices + + + + +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, essayez d'appuyer sur les touches `flèche haut` et `flèche bas` pour retrouver les dernières commandes que vous avez tapées. + +* * * + +### Exercice ! + +Un 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 : + + + +{% filename %}command-line{% endfilename %} + + $ cd exercices + $ mkdir test + $ ls + test + + + + + + +{% filename %}command-line{% endfilename %} + + > cd exercices + > mkdir test + > dir + 05/08/2020 07:28 PM test + + + + +Félicitations ! :) + +* * * + +### Nettoyage + +Supprimons tout ce qu'on vient de faire, histoire d'éviter de laisser du bazar. + +D'abord, revenons au Bureau : + + + +{% filename %}command-line{% endfilename %} + + $ cd .. + + + + + + +{% filename %}command-line{% endfilename %} + + > cd .. + + + + +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 : + + + +{% filename %}command-line{% endfilename %} + + $ pwd + /Users/olasitarska/Bureau + + + + + + +{% filename %}command-line{% endfilename %} + + > cd + C:\Users\olasitarska\Bureau + + + + +Maintenant, il est temps de supprimer le 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. + + + +{% filename %}command-line{% endfilename %} + + $ rm -r exercices + + + + + + +{% filename %}command-line{% endfilename %} + + > rmdir /S exercices + exercices, Are you sure ? Y + + + + +Et voilà ! Pour être sure que le dossier a bien été supprimé, vérifions : + + + +{% filename %}command-line{% endfilename %} + + $ ls + + + + + + +{% filename %}command-line{% endfilename %} + + > dir + + + + +### Sortir + +C'est tout pour le moment ! Vous pouvez maintenant fermer la ligne de commande. Faisons-le à la manière des bidouilleurs⋅euses, d’accord ? :) + + + +{% filename %}command-line{% endfilename %} + + $ exit + + + + + + +{% filename %}command-line{% endfilename %} + + > exit + + + + +Cool, non ? :) + +## Résumé + +Voici un résumé de quelques commandes utiles : + +| Commande (Windows) | Commande (macOS / Linux) | Description | Exemple | +| ------------------ | ------------------------ | -------------------------------- | ------------------------------------------------- | +| exit | exit | ferme la fenêtre | **exit** | +| cd | cd | change le dossier courant | **cd test** | +| cd | pwd | montre le dossier courant | **cd** (Windows) ou **pwd** (macOS / Linux) | +| dir | ls | liste des fichiers/dossiers | **dir** | +| copy | cp | copie un fichier | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | déplace un fichier | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | crée un nouveau dossier | **mkdir testdirectory** | +| rmdir (or del) | rm | supprime un fichier | **del c:\test\test.txt** | +| rmdir /S | rm -r | supprime un répertoire | **rm -r testdirectory** | +| [CMD] /? | man [CMD] | affiche l'aide pour une commande | **cd /?** (Windows) ou **man cd** (macOS / Linux) | + +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 curieuse, [ss64.com](http://ss64.com) contient une référence complète de toutes les commandes pour tous les systèmes d'exploitation. + +## Vous êtes prête ? + +Plongeons dans Python ! \ No newline at end of file diff --git a/fr-FR/intro_to_command_line/open_instructions.md b/fr-FR/intro_to_command_line/open_instructions.md new file mode 100644 index 00000000000..608e1c81425 --- /dev/null +++ b/fr-FR/intro_to_command_line/open_instructions.md @@ -0,0 +1,28 @@ + + +Une des procédures suivantes, selon votre version de Windows et votre clavier, devrait vous permettre d'ouvrir l'invite de commande (il est possible que vous deviez vous débrouiller un peu jusqu'à ce que vous trouvez la bonne) : + +- Allez dans le menu ou écran de démarrage et tapez "Invite de commande" dans l'outil de recherche. +- Cliquez sur le Menu démarrer→ Système Windows → Invite de commandes. +- Aller dans Menu démarrer → Tous les programmes → Accessoires → Invite de commandes. +- Allez sur l’écran de démarrage, passez votre souris dans le coin inférieur gauche de l’écran et cliquez sur la flèche qui s’affiche (sur un écran tactile, plutôt balayer du bas vers le haut de l’écran). La page Apps doit s’ouvrir. Cliquez sur invite de commandes dans la section Système Windows. +- Maintenez la touche Windows enfoncée et appuyez sur la touche « X » de votre clavier. Choisissez « Invite de commandes » dans le menu contextuel. +- Maintenez la touche Windows enfoncée et appuyez sur la touche « R » pour ouvrir une fenêtre « Exécuter ». Tapez « cmd », puis cliquez sur la touche OK. + +![Tapez "cmd" dans la fenêtre "Exécuter"](../python_installation/images/windows-plus-r.png) + +Plus loin dans ce tutoriel, vous aurez besoin de deux fenêtres ouvertes en même temps. Toutefois, sur certaines versions de Windows, si vous avez déjà une fenêtre de commande ouverte et que vous essayez d’en ouvrir une seconde utilisant la même méthode, vous serez renvoyées vers la fenêtre de commande que vous avez déjà ouvert. Essayez-le maintenant sur votre ordinateur pour voir ce qui se passe ! Si vous obtenez seulement une fenêtre de commande, essayez l’une des autres méthodes dans la liste ci-dessus. Au moins une d'entre elles devrait vous donner une nouvelle fenêtre de commande. + + + + + +Allez sur Applications → Utilitaires → Terminal. + + + + + +C’est probablement sous Applications → Accessoires → Terminal ou Applications → Système → Terminal, mais cela peut dépendre de votre système. Si toujours rien, vous pouvez demander à Google. :) + + \ No newline at end of file diff --git a/fr-FR/python_installation/README.md b/fr-FR/python_installation/README.md new file mode 100644 index 00000000000..dd80800b48e --- /dev/null +++ b/fr-FR/python_installation/README.md @@ -0,0 +1,15 @@ +# Commençons par Python + +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. 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. C'est pourquoi il semble plus simple que les autres langages de programmation, mais ne vous inquiétez pas - Python est aussi extrêmement puissant ! + +# Installation de Python + +> **Note** Si vous utilisez un Chromebook, passez ce chapitre et prenez soin de suivre les instructions de [configuration pour Chromebook](../chromebook_setup/README.md). +> +> **Note **Si vous avez déjà effectué [l'Installation](../installation/README.md) vous devriez déjà avoir fait ce qui suit. Vous pouvez donc passer directement au chapitre suivant ! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/fr-FR/python_installation/instructions.md b/fr-FR/python_installation/instructions.md new file mode 100644 index 00000000000..c2722c45e34 --- /dev/null +++ b/fr-FR/python_installation/instructions.md @@ -0,0 +1,117 @@ +> Pour les lecteur·rices autodidactes (et qui n'ont pas de soucis avec l'anglais) : Ce chapitre est traité dans la vidéo [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA). +> +> Cette section repose sur un tutoriel de 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 l'installer ! Pour suivre ce tutoriel, l'idéale est d'installer la dernière version de Python 3. Si vous avez une version antérieure, il va falloir la mettre à jour. Si vous avez déjà la version {{ book.py_min_version }} ou supérieure, ça devrait aller. + +Veuillez installer Python comme suit, même si vous avez déjà installé Anaconda sur votre ordinateur. + + + +Vérifiez d'abord si votre ordinateur exécute une version 32 bits ou une version 64 bits de Windows, en cherchant "Type du système" dans la page d'information système. Pour accéder à cette page, essayez l'une de ces méthodes : + +* Appuyez sur la touche Windows et la touche Pause/Attn en même temps +* Ouvrez votre panneau de configuration depuis le menu Windows, puis naviguez vers Système et sécurité, puis Système +* Appuyez sur la touche Windows, puis accédez à Paramètres > Système > A propos +* Recherchez dans le menu Démarrer Windows le raccourci "Informations système". Pour ce faire, cliquez sur le bouton Démarrer ou appuyez sur la touche Windows, puis commencez à taper `Informations système`. Des entrées correspondantes apparaîtrons dès que vous tapez. Vous pouvez sélectionner l'entrée une fois qu'elle apparaît. + +Vous pouvez télécharger Python pour Windows depuis le site web https://www.python.org/downloads/windows/. Cliquez sur le lien "Latest Python 3 Release - Python x.x.x". Si votre ordinateur exécute une version **64-bit** de Windows, téléchargez l'installateur exécutable **Windows x86-64 executable installer**. Sinon, téléchargez **Windows x86 executable installer**. Après avoir téléchargé l'installateur, vous devriez l'exécuter (double-cliquez dessus) et suivre les instructions. + +Une chose à surveiller : lors de l’installation, vous remarquerez une fenêtre marquée « Setup ». Assurez-vous de cocher la case "Add Python {{ book.py_version }} to PATH" ou "Add Python to your environment variables" et cliquez sur "Install Now", comme indiqué ici (cela peut s'afficher un peu différemment si vous installez une autre version): + +![N'oubliez pas d'ajouter Python à votre chemin (path)](../python_installation/images/python-installation-options.png) + +Une fois l’installation terminée, vous verrez une boîte de dialogue contenant un lien que vous pouvez suivre pour en savoir plus sur Python ou sur la version que vous avez installée. Fermez ou annulez cette boîte de dialogue -- vous en apprendrez plus dans ce tutoriel ! + +Note : Si vous utilisez une ancienne version de Windows (7, Vista, ou n'importe quelle version antérieure) et l'installateur Python {{ book.py_version }} échoue avec une erreur, alors installez toutes les mises à jour Windows et essayez d'installer Python à nouveau. Si vous avez toujours l'erreur, essayez d'installer la version {{ book.py_min_release }} de Python depuis [Python.org](https://www.python.org/downloads/windows/). + +> Django {{ book.django_version }} a besoin de Python {{ book.py_min_version }} ou plus récent, qui n'est pas pris pas en charge par Windows XP ou les versions précédentes. + + + + + +> **Note** Avant d'installer Python sur OS X, vous devriez vous assurer que vos paramètres Mac permettent d'installer des programmes qui ne proviennent pas de l'App Store. Allez dans Préférences Système (c'est dans le dossier Applications), cliquez sur "Sécurité & Confidentialité", puis sur l'onglet "Général". Si votre "Autoriser les applications téléchargées de:" est défini sur "Mac App Store", changez-le à "Mac App Store et développeurs identifiés". + +Vous devez aller sur le site https://www.python.org/downloads/mac-osx/ 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-{{ book.py_release }}-macosx10.9.pkg* pour lancer l'installateur. + + + + + +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 : + +{% filename %}ligne de commande{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +Si vous avez une version différente de Python installée, au moins {{ book.py_min_version }} (par exemple {{ book.py_min_release }}), vous n'avez pas besoin de mettre à jour Python. Si Python n'est pas installé, ou si vous voulez une version différente, vérifiez d'abord la distribution Linux que vous utilisez avec la commande suivante : + +{% filename %}command-line{% endfilename %} + + $ grep '^NAME=' /etc/os-release + + +Ensuite, selon le résultat, suivez l'un des guides d'installation sous cette section. + + + + + +Tapez cette commande dans votre terminal : + +{% filename %}ligne de commande{% endfilename %} + + $ sudo apt install python3 + + + + + + +Tapez cette commande dans votre terminal : + +{% filename %}ligne de commande{% endfilename %} + + $ sudo dnf install python3 + + +Si vous utilisez une ancienne version de Fedora, vous pourriez avoir une erreur disant que la commande `dnf` n'est pas trouvée. Dans ce cas, vous devez utiliser la commande `yum` à la place. + + + + + +Tapez cette commande dans votre terminal : + +{% filename %}ligne de commande{% endfilename %} + + $ sudo zypper install python3 + + + + +Vérifiez que l'installation s'est bien déroulée en ouvrant votre terminal et en lançant la commande `python3`: + +{% filename %}ligne de commande{% endfilename %} + + $ python3 --version + Python {{ book.py_release }} + + +La version affichée peut être différente de {{ book.py_release }} -- elle devrait correspondre à la version que vous avez installée. + +**NOTE:** Si vous êtes sur Windows et que vous obtenez un message d'erreur disant que `python3` n'a pas été trouvé, essayez d'utiliser `python` (sans `3`) et vérifiez si elle lance une version de Python {{ book.py_min_version }} ou ultérieure. Si cela ne fonctionne pas non plus, vous pouvez ouvrir une nouvelle ligne de commande et réessayer ; cela se produit si vous utilisez une fenêtre de ligne de commande datant d'avant l'installation de Python. + +* * * + +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. \ No newline at end of file diff --git a/fr-FR/python_introduction/README.md b/fr-FR/python_introduction/README.md new file mode 100644 index 00000000000..559d3a226e6 --- /dev/null +++ b/fr-FR/python_introduction/README.md @@ -0,0 +1,1072 @@ +{% set warning_icon = '' %} + +# Introduction à Python + +> Une partie de ce chapitre s’inspire du tutoriel des Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Allons écrire du code ! + +## Le prompt Python + +> Pour les lecteurs à la maison: cette partie est couverte dans la vidéo [Python Basics: Integers, Strings, Lists, Variables and Errors](https://www.youtube.com/watch?v=MO63L4s-20U) . + +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](/intro_to_command_line/README. html). + +Dès que vous êtes prête, suivez les instructions suivantes. + +Afin d'ouvrir une console Python, tapez `python` sous Windows ou `python3` sous Mac OS/Linux et appuyez sur `entrée`. + +{% filename %}command-line{% endfilename %} + + $ python3 + Python {{ book.py_release }} (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Votre première commande Python ! + +Après avoir lancé la commande Python, votre prompt (ou invite de commandes) a changé en `>>>`. Cela signifie que maintenant, les seules commandes que nous pouvons taper sont des commandes appartenant au langage Python. Vous n'avez pas besoin de taper `>>>` - Python fait ça pour vous. + +Si vous voulez quitter 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 `>>>`. + +Pour l'instant, nous ne voulons pas quitter la console Python. Nous voulons en savoir plus. Commençons par écrire quelques operations mathématiques, comme `2 + 3` suivi par la touche `entrée`. + +{% filename %}command-line{% endfilename %} + +```python +>>> 2 + 3 +5 +``` + +Pas mal, non ? Vous avez vu comment la réponse a surgi ? Python s'y connait en math ! Vous pouvez essayer d’autres commandes comme : + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +Pour effectuer un calcul exponentiel, disons 2 à la puissance 3, nous tapons : {% filename %}ligne de commande{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` + +Amusez-vous un peu avec ça, et revenez ici après. :) + +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… + +## Chaines de caractères (Strings) + +Et si nous essayions avec votre nom ? Tapez votre prénom entre guillemets, comme cela : + +{% filename %}command-line{% endfilename %} + +```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. Çela 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. + +Il est possible d'assembler des chaines de caractères comme ceci : + +{% filename %}command-line{% endfilename %} + +```python +>>> "Salut " + "Ola" +'Salut Ola' +``` + +Vous pouvez aussi multiplier une chaîne de caractères par un nombre : + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` + +Si vous avez besoin de mettre une apostrophe dans votre chaine de caractères, vous avez deux possibilités. + +Vous pouvez utiliser des guillemets doubles : + +{% filename %}command-line{% endfilename %} + +```python +>>> "J'aime la mousse au chocolat" +"J'aime la mousse au chocolat" +``` + +ou échapper l’apostrophe avec une barre oblique inversée (un backslash, `\`) : + +{% filename %}command-line{% endfilename %} + +```python +>>> 'J\'aime la mousse au chocolat' +"J'aime la mousse au chocolat" +``` + +Pas mal, non ? Pour voir votre nom en majuscules, tapez juste : + +{% filename %}command-line{% endfilename %} + +```python +>>> "Ola".upper() +'OLA' +``` + +Vous venez d'utiliser la **fonction** `upper` sur votre chaine de caractères! Une méthode (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 ! + +{% filename %}command-line{% endfilename %} + +```python +>>> len("Ola") +3 +``` + +Vous avez peut-être remarqué que parfois, on appelle la fonction avec `.` en la plaçant après la chaine de caractères (comme `"Ola".upper()`) alors qu'à d'autres moment, on appelle d'abord la fonction puis la chaine 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 chaines 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 chaines 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 chaines de caractères** – dans Python, les nombres sont utilisés pour faire des calculs, et les chaines de caractères pour manipuler du texte +- **opérateurs** – comme `+` et `*`, ils combinent des valeurs pour en produire une nouvelle +- **les fonctions** – comme `upper()` et `len()` qui effectuent des actions sur les objets. + +Ce sont des bases présentes dans tous les langages de programmation existants. Prête pour quelque chose de plus compliqué ? Allons-y ! + +## Les erreurs + +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` : + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +Nous avons eu notre première erreur! L'icône {{ warning_icon }} est notre façon de vous alerter que le code que vous êtes sur le point d'exécuter ne fonctionnera pas comme prévu. Faire des erreurs (même intentionnellement) est une partie importante de l'apprentissage! + +L'erreur que nous venons d'avoir 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 chaine de caractères ? Après tout, les chaînes de caractères ont bien une taille, non ? + +{% filename %}command-line{% endfilename %} + +```python +>>> len(str(304023)) +6 +``` + +Ça a marché ! Nous avons utilisé la fonction `str` à l'intérieur de la fonction `len`. La fonction `str()` convertit n'importe quoi en chaine de caractères. + +- La fonction `str` convertit des choses en **chaines de caractères** +- La fonction `int` convertit des choses en **entiers** + +> 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 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 que nous aimerions créer une variable appelée `name` : + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Ola" +``` + +Nous tapons name égale 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 `name` et appuyez sur `entrée` : + +{% filename %}command-line{% endfilename %} + +```python +>>> name +'Ola' +``` + +Youpi ! Votre première variable ! :) Vous pouvez toujours changer ce à quoi elle fait référence : + +{% filename %}command-line{% endfilename %} + +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` + +Vous pouvez aussi l'utiliser avec des fonctions : + +{% filename %}command-line{% endfilename %} + +```python +>>> len(name) +5 +``` + +Génial, non ? Et bien sûr, les variables peuvent être n'importe quoi, y compris des nombres ! Essayez ça : + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +Mais que ce passe-t-il si nous utilisons le mauvais nom ? Essayez de deviner ! C'est parti ! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```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érifiez dans votre code que vous n'avez pas fait une faute de frappe dans une variable. + +Jouez un peu avec les variables et essayez de voir ce que vous pouvez en faire ! + +## La fonction print + +Essayez ça : + +{% filename %}command-line{% endfilename %} + +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` + +Quand vous tapez `name`, l'interpréteur Python répond avec la *représentation* de la chaine 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 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 + +En plus des chaines 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é **list** (liste). Les listes sont exactement ce que vous pensez : des objets qui sont des listes d’autres objets. :) + +Allez-y, créez une liste : + +{% filename %}command-line{% endfilename %} + +```python +>>> [] +[] +``` + +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 : + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +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à ! + +{% filename %}command-line{% endfilename %} + +```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 : + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.sort() +``` + +Ç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é : + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +Comme vous pouvez le voir, les nombres de la liste sont maintenant triés du plus petit au plus grand. Bravo ! + +Pouvons-nous inverser cet ordre ? Essayons! + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +Si vous voulez ajouter quelque chose à la liste, vous pouvez le faire en tapant cette commande : + +{% filename %}command-line{% endfilename %} + +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +Si vous ne souhaitez afficher que le premier élément, vous pouvez le faire en utilisant des **indices**. Un indice est un nombre qui indique où se trouve un élément 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 : + +{% filename %}command-line{% endfilename %} + +```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. + +Pour supprimer quelque chose de votre liste, vous devrez utiliser les **indices** comme nous l'avons appris ci-dessus et la méthode `pop()` . Essayons l'exemple suivant : supprimez le premier élément de votre liste. + +{% filename %}command-line{% endfilename %} + +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +59 +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +Ça marche à merveille ! + +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 ses 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 + +> Pour les lectrices autodidactes : cette partie est traitée dans la vidéo [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c). + +Un dictionnaire est un peu comme une liste. Cependant, nous utilisons des clefs plutôt que des indices numériques pour accéder aux valeurs. Une clef peut être n'importe quelle chaîne de caractères ou n'importe quel nombre. La syntaxe pour définir un dictionnaire vide est la suivante : + +{% filename %}command-line{% endfilename %} + +```python +>>> {} +{} +``` + +Cela montre que vous venez de créer un dictionnaire vide. Hurray ! + +Maintenant, essayez d'écrire la commande suivante (et essayez aussi de remplacer le contenu par vos informations) : + +{% filename %}command-line{% endfilename %} + +```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 objet `chaine de caractères`), +- `country` pointe vers `'Poland'` (une autre `chaine 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 : + +{% filename %}command-line{% endfilename %} + +```python +>>> print(participant['name']) +Ola +``` + +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. + +Que ce passe-t-il lorsque nous demandons à Python la valeur correspondant à une clef qui n'existe pas ? Pouvez-vous le deviner ? Essayons voir ! + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` + +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. + +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 : + +{% filename %}command-line{% endfilename %} + +```python +>>> participant['favorite_language'] = 'Python' +``` + +Comme pour les listes, la fonction `len()` permet d'obtenir le nombre de paires clef–valeur du dictionnaire. Essayez de taper la commande suivante : + +{% filename %}command-line{% endfilename %} + +```python +>>> len(participant) +4 +``` + +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 méthode `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 : + +{% filename %}command-line{% endfilename %} + +```python +>>> participant.pop('favorite_numbers') +[7, 42, 92] +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Comme vous pouvez le voir dans votre console, la paire clef–valeur correspondant à "favorite_numbers" a été supprimée. + +De même, vous pouvez changer la valeur associée à une clef déjà créée dans le dictionnaire. Tapez ceci : + +{% filename %}command-line{% endfilename %} + +```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. + +### Résumé + +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 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 + +On continue ? :) + +## Comparer des choses + +> Pour les lectrices autodidactes : cette partie est traitée dans la vidéo [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4). + +Comparer des choses est très important en programmation. Quelle serait la chose la plus facile à comparer ? Les nombres, bien sûr ! Allons voir comment ça marche : + +{% filename %}command-line{% endfilename %} + +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +>>> len([1, 2, 3]) > len([4, 5]) +True +``` + +Nous avons donné à Python quelques nombres à comparer. Comme vous pouvez le voir, Python n'est pas seulement capable de comparer des nombres, mais il peut aussi comparer les valeurs des expressions mathématiques comme `2 * 2` avec le résultat d'une fonction comme le `2` renvoyé par `len([4, 5])`. Pas mal, non ? + +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 : + +{% filename %}command-line{% endfilename %} + +```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 `>` 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 : + +{% filename %}command-line{% endfilename %} + +```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 que vous le souhaitez et il vous donnera une réponse. Plutôt malin, non ? + +- **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 : + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: '>' not supported between instances of 'int' and 'str' +``` + +Comme vous le voyez, Python n'est pas capable de comparer un nombre (`int`) et une chaine 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 + +Vous venez d'apprendre un nouveau type d'objet en Python. Il s'appelle **Boolean**. + +Il n'y a que deux objets Booléens : + +- True (vrai) +- False (faux) + +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 ! Regardez : + +{% filename %}command-line{% endfilename %} + +```python +>>> a = True +>>> a +True +``` + +Vous pouvez aussi faire ça : + +{% filename %}command-line{% endfilename %} + +```python +>>> a = 2 > 5 +>>> a +False +``` + +Entraînez-vous et amusez-vous avec les Booleéns en essayant de lancer les commandes suivantes : + +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` + +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 les lectrices autodidactes : cette partie est traitée dans la vidéo [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk). + +Pour l'instant, nous avons écrit tout notre code Python directement dans l'interpréteur, ce qui nous limite à une ligne de code à la fois. Les programmes sont typiquement sauvegardés dans des fichiers et sont exécutés par **l'interpréteur** ou le **compilateur** de notre langage de programmation. Jusqu'à présent, nous avons lancé nos programmes une ligne à la fois dans **l'interprèteur** Python. Nous aurons besoin de plus d'une ligne de code pour les prochaines tâches, donc nous aurons rapidement besoin de : + +- Quitter l'interpréteur Python ; +- Ouvrir l'éditeur de code de notre choix ; +- 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()` + +{% filename %}command-line{% endfilename %} + +```python +>>> exit() +$ +``` + +Cela vous ramènera dans la ligne de commande de votre système d'exploitation. + +Tout à l'heure, nous avions choisi un éditeur de code de la section [code editor](../code_editor/README.md). Nous allons maintenant ouvrir l'éditeur et écrire du code dans un nouveau fichier (ou, si vous utilisez un Chromebook, créez un nouveau fichier dans le cloud IDE et ouvrez le fichier, qui sera dans l'éditeur de code inclus) : + +{% filename %}editor{% endfilename %} + +```python +print('Hello, Django girls!') +``` + +Vous avez maintenant pas mal de connaissances en Python : n'hésitez pas à écrire du code avec ce que vous avez appris aujourd'hui ! + +Maintenant, nous devons sauvegarder le fichier et lui donner un nom descriptif. Appelons le fichier **python_intro.py** et sauvegardons-le sur votre 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. + +> **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`, par exemple, n'a pas la même couleur d'une chaîne de caractères. 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 chaine 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 tard). C'est ce genre de fonctionnalités qui font que vous aimerez rapidement programmer avec un éditeur de code. :) + +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 à : + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + + + + + +Sur Linux, ce sera comme ça : + +{% filename %}command-line{% endfilename %} + + $ cd ~/Desktop + + +(N'oubliez pas que le mot "Bureau" peut être traduit dans votre langue locale.) + + + + + +Dans l'invite de commande Windows, ce sera comme ceci : + +{% filename %}command-line{% endfilename %} + + > cd %HomePath%\Desktop + + + + + + +Et sur Windows Powershell, ce sera comme ça : + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + + +Si vous êtes coincées, demandez de l'aide. C'est exactement pour ça que les coaches sont là ! + +Maintenant, utilisez Python pour exécuter le code contenu dans votre fichier : + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hello, Django girls! + + +Note: sur Windows 'python3' n'est pas reconnu comme une commande. Au lieu de cela, utilisez 'python' pour exécuter le fichier : + +{% filename %}command-line{% endfilename %} + +```python +> python python_intro.py +``` + +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 de 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). + +Remplacez le code dans votre fichier **python_intro.py** avec ceci : + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: +``` + +Si nous sauvegardons ce fichier et que nous l'exécutons, nous obtiendrons l'erreur suivante : + +{% filename %}{{ warning_icon }} command-line{% endfilename %} + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +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 : + +{% filename %}python_intro.py{% endfilename %} + +```python +if 3 > 2: + print('Ça marche !') +``` + +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. La touche de tabulation (Tab) devrait ajouter automatiquement 4 espaces, mais cela peut dépendre du paramétrage de votre éditeur de texte. Lorsque vous avez fait votre choix, ne le changez pas ! Si vous avez déjà indenté avec 4 espaces, faites de même dans le reste du fichier - sinon vous risquez de rencontrer des problèmes. + +Sauvegardez le fichier et relancez le : + +{% filename %}command-line{% endfilename %} + +```python +$ python3 python_intro.py +Ça marche ! +``` + +Note: N'oubliez pas que sur Windows, 'python3' n'est pas reconnu comme une commande. À partir de maintenant, remplacez 'python3' par 'python' pour exécuter le fichier. + +### Et que se passe-t-il si une condition n’est pas vraie ? + +Dans les exemples précédents, Python a exécuté du code parce que celui-ci se trouvait sous une condition qui était vraie. Cependant, Python possède aussi des instructions `elif` (sinon si) et `else` (sinon) : + +{% filename %}python_intro.py{% endfilename %} + +```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 : + +{% filename %}command-line{% endfilename %} + + $ 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. Voyons comment `elif` fonctionne : + +{% filename %}python_intro.py{% endfilename %} + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + +Exécutons le code : + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hey Sonja! + + +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 : + +{% 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 va tester les différentes conditions puis il affichera ceci : + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Parfait, je peux entendre tous les détails du morceau. + + +## Commentaires + +Les commentaires sont des lignes commençant par `#`. Vous pouvez écrire ce que vous voulez après le `#` et Python va l'ignorer. Les commentaires peuvent rendre votre code plus facile à comprendre pour d'autres personnes. + +Voyons à quoi cela ressemble : + +{% 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!") +``` + +Vous n'avez pas besoin d'écrire un commentaire pour chaque ligne de code, mais il est utile parfois d'expliquer pourquoi votre code fait une certaine chose, ou de fournir un résumé pour les parties les plus complexes. + +### Résumé + +Avec ces derniers exercices, vous avez appris : + +- **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` +- **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. +- **commentaires** – lignes que Python n'exécutera pas et qui vous permettent de documenter votre code. + +Il est temps d'attaquer la dernière partie de ce chapitre ! + +## Vos propres fonctions ! + +> Pour les lectrices autodidactes : cette partie est traitée dans la vidéo [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0). + +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. Essayons ! Remplacer le code de **python_intro.py** par ceci : + +{% filename %}python_intro.py{% endfilename %} + +```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. Quand nous écrivons `def hi():` et les lignes indentées qui suivent, nous écrivons les instructions disant ce que la fonction `hi` doit faire. Python va lire et mémoriser ces instructions, mais ne va pas exécuter la fonction tout de suite. Pour dire à Python que nous voulons exécuter la fonction, nous devons appeler la fonction avec `hi()`. Python lit le fichier et l’exécute de haut en bas, donc nous devons définir la fonction dans le fichier avant de l’appeler. + +Lançons notre code pour voir ce qui se passe : + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi there! + How are you? + + +Note : si cela n'a pas fonctionné, ne paniquez pas ! Le message d'erreur vous aidera à comprendre pourquoi : + +- Si vous obtenez un `NameError`, cela est du probablement à une faute de frappe, donc vous devriez vérifier d'avoir utilisé le même nom lors de la création de la fonction avec `def hi():` et lors de l'appel avec `hi()`. +- Si vous obtenez un `IndentationError`, vérifiez que les deux `print` sont à la même distance du début de leur ligne: python veut que tout le code à l'intérieur de la fonction soit bien aligné. +- Si vous n'obtenez rien du tout, vérifiez que le `hi()` à la fin *n'est pas indenté*. Si c'est le cas, cette ligne est considérée par Python comme faisant partie de la fonction, et elle ne sera donc jamais exécutée. + +Construisons maintenant notre première fonction avec des paramètres. Dans l'exemple précédent, nous avions une fonction que disait "Hi there!" à la personne qui la lançait. Faisons une fonction identique, mais ajoutons un nom cette fois-ci : + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): +``` + +Comme vous le voyez, nous avons donné à notre fonction un paramètre appelé `name` : + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +hi() +``` + +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 remplie. Voyons comment ça marche : + +{% filename %}{{ warning_icon }} 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' + + +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 oublié de passer cet argument lorsque nous avons appelé notre fonction. Corrigeons la dernière ligne du fichier : + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Ola") +``` + +Et exécutez votre code à nouveau : + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Ola! + + +Et que se passe-t-il quand on change de nom ? + +{% filename %}python_intro.py{% endfilename %} + +```python +hi("Sonja") +``` + +Exécutez votre code à nouveau : + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Sonja! + + +Maintenant, que pensez-vous qu'il se passera lorsque nous écrivrons un autre nom (ni Ola, ni Sonja) ? Faites un essai et regardez si vous avez raison. Ceci devrait s'afficher : + +{% filename %}command-line{% endfilename %} + + Hi anonymous! + + +Super, non ? Avec ça, vous n'avez pas besoin de répéter de lignes de code 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 quelque chose de plus intelligent – il existe bien plus que deux noms, et écrire une condition pour chacun d'entre eux serait difficile, non ? Remplacez le contenu de votre fichier avec les suivants : + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + +Exécutons à nouveau notre code : + +{% filename %}command-line{% endfilename %} + + $ python3 python_intro.py + Hi Rachel! + + +Félicitations ! Vous venez juste d’apprendre à écrire des fonctions ! :) + +## Les boucles + +> Pour les lectrices autodidactes : cette partie est traitée dans la vidéo [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0). + +C’est déjà la dernière partie. C’était rapide, non ? :) + +Les programmeurs⋅euses n'aiment pas devoir se répéter. L'essence de la programmation est d'automatiser les choses. Pour reprendre l'exemple précédent, nous aimerions pouvoir saluer automatiquement chaque personne. Pour cela, nous allons utiliser des boucles. + +Vous vous souvenez des listes ? Faisons une liste de filles : + +{% filename %}python_intro.py{% endfilename %} + +```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-la donc dans une boucle : + +{% filename %}python_intro.py{% endfilename %} + +```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. + +Voilà le code complet à mettre dans votre fichier : + +{% filename %}python_intro.py{% endfilename %} + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + +Exécutez votre code : + +{% 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 + + +Comme vous pouvez le constater, tout ce que vous mettez dans la déclaration `for` avec une indentation sera répété pour chaque élément de la liste `filles`. + +Vous pouvez aussi utiliser `for` sur des nombres grâce à la fonction `range`: + +{% filename %}python_intro.py{% endfilename %} + +```python +for i in range(1, 6): + print(i) +``` + +Cela va afficher : + +{% filename %}command-line{% endfilename %} + + 1 + 2 + 3 + 4 + 5 + + +`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'inclue pas 6). Cela est du au fait que "range" est semi-ouvert, c'est-à-dire qu'il prend en compte la première valeur mais pas la dernière. + +## Résumé + +Et voilà ! **Vos assurez un max !** C'était un chapitre difficile, donc vous pouvez être fières de vous. De notre côté, nous sommes fières de vous, pour être parvenu-e si loin dans le cours. Bravo ! + +Pour accéder au tutoriel officiel et complet de Python, visitez https://docs.python.org/3/tutorial/. Cela vous donnera un accès plus exhaustif à l'étude du langage. A bientôt! :) + +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](images/cupcake.png) \ No newline at end of file diff --git a/fr-FR/template_extending/README.md b/fr-FR/template_extending/README.md new file mode 100644 index 00000000000..909b525e6df --- /dev/null +++ b/fr-FR/template_extending/README.md @@ -0,0 +1,151 @@ +# Héritage de template + +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. + +Les modèles permettent d'utiliser les mêmes informations ou mises en page en plusieurs endroits. Vous n'avez pas à vous répéter dans chaque fichier. Et si vous voulez changer quelque chose, vous n'avez pas à le faire dans chaque modèle, mais juste un! + +## 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/` : + + blog + └───templates + └───blog + base.html + post_list.html + + +Ensuite, ouvrez ce fichier dans l'éditeur de code et collez-y tout ce qui se trouve dans le fichier `post_list.html`. Ça devrait ressembler à ça : + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% load static %} + + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Puis, dans le fichier `base.html`, remplacez tout ce qui se trouve dans `` (de `` à ``) par ceci : + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +{% raw %}Vous pouvez remarquer qu'on vient de remplacer tout ce qui était entre `{% for post in posts %}` et `{% endfor %}` avec : {% endraw %} + +{% filename %}blog/templates/blog/base.html{% endfilename %} + +```html +{% block content %} +{% endblock %} +``` + +Mais pourquoi? Vous venez de créer un `block` ! Vous avez utilisé la balise de modèle `{% block %}` pour créer une partie qui va contenir du HTML. Ce HTML viendra d'un autre modèle qui étendra ce modèle-ci (`base.html`). Nous vous expliquerons comment faire cela dans un instant. + +Enregistrez `base.html` et ouvrez votre `blog/templates/blog/post_list.html` à nouveau dans l'éditeur de code. {% raw %}Vous allez tout supprimer au-dessus de `{% for post in posts %}` et en dessous de `{% endfor %}`. Lorsque vous avez terminé, le fichier ressemblera à ceci :{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +Nous voulons utiliser ceci dans le cadre de notre modèle pour tous les blocs 'content'. Il est temps d'ajouter ajouter des balises block à ce fichier ! + +{% raw %}Vous voulez que votre balise block corresponde à la balise dans votre fichier `base.html` . Vous voulez aussi qu'il inclue tout le code qui appartient à vos blocs de contenu. Pour faire cela, entourez tout le code de `{% block content %}` et `{% endblock %}`. Comme ceci :{% endraw %} + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Seule une chose reste à faire. Nous devons connecter ces deux modèles ensemble. C'est ça, étendre des modèles ! Nous allons le faire en ajoutant une balise 'extends' au début du fichier. Comme cela : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+ +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` + +Et voilà ! Enregistrez le fichier et vérifiez que votre site fonctionne toujours correctement. :) + +> Si vous obtenez l'erreur `TemplateDoesNotExist`, cela signifie qu'il n'y a pas de fichier `blog/base.html` et que vous avez `runserver` en cours d'exécution dans la console. Arrêtez-le (en appuyant simultanément sur Ctrl+C, les touches Control et C de votre clavier) et relancez-le en tapant la commande `python manage.py runserver`. \ No newline at end of file diff --git a/fr-FR/whats_next/README.md b/fr-FR/whats_next/README.md new file mode 100644 index 00000000000..0437a65605c --- /dev/null +++ b/fr-FR/whats_next/README.md @@ -0,0 +1,43 @@ +# Et maintenant ? + +Un immense bravo à vous ! **Vous êtes très déterminée**. Nous sommes fières ! <3 + +### Que faire maintenant ? + +Faites une pause et détendez-vous ! Vous venez d'accomplir quelque chose de conséquent. + +Ensuite, suivez Django Girls sur [Facebook](http://facebook.com/djangogirls) ou [Twitter](https://twitter.com/djangogirls) pour être au courant des nouvelles. + +### À la recherche de ressources supplémentaires ? + +Oui ! Il y a *énormément* de ressources en ligne pour apprendre toutes sortes de compétences de programmation. Il peut être assez difficile de s'orienter et aller plus loin, mais nous vous donnons des pistes pour démarrer. Quelle que soit la raison qui vous a menée à participer à Django Girls, et quels que soient les intérêts que vous avez développés en suivant le tutoriel, voici quelques ressources gratuites (ou des ressources avec de grands composants gratuits) que vous pouvez utiliser pour atteindre vos objectifs. + +#### Django + +- Notre autre livre, [Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/) +- [Tutoriel officiel de Django](https://docs.djangoproject.com/en/2.2/intro/tutorial01/) +- [Vidéos Getting Started With Django](http://www.gettingstartedwithdjango.com/) +- [La spécialisation Python de Coursera](https://www.coursera.org/specializations/django) – vous pouvez accéder gratuitement à certains cours et vous pouvez obtenir un certificat Coursera à la fin + +#### HTML, CSS et JavaScript + +- [Cours de développement web de la Codecademy](https://www.codecademy.com/learn/paths/web-development) +- [freeCodeCamp](https://www.freecodecamp.org/) + +#### Python + +- [Cours Python de la Codecademy](https://www.codecademy.com/learn/learn-python) +- [Cours Python de Google](https://developers.google.com/edu/python/) +- Le livre [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) – les premiers exercices sont gratuits +- [New Coder tutorials](http://newcoder.io/tutorials/) – c'est une série d'exemples pratiques illustrant comment Python peut vous servir +- [edX](https://www.edx.org/course?search_query=python) – vous pouvez accéder à la plupart des cours gratuitement, mais si vous voulez un certificat ou des crédits pour une qualification supérieure, cela coûtera de l'argent +- [La spécialisation Python de Coursera](https://www.coursera.org/specializations/python) – vous pouvez accéder gratuitement à certains cours et vous pouvez obtenir un certificat à la fin +- [Python for Everybody](https://www.py4e.com/) – une version gratuite et ouverte de la spécialisation de Coursera "Python for Everybody" + +#### Travailler avec les données + +- [Cours de science des données de la Codecademy](https://www.codecademy.com/learn/paths/data-science) +- [edX](https://www.edx.org/course/?search_query=python&subject=Data%20Analysis%20%26%20Statistics) – vous pouvez accéder à la plupart des cours gratuitement, mais si vous voulez un certificat ou des crédits pour une qualification supérieure, cela coûtera de l'argent +- [Dataquest](https://www.dataquest.io/) – les 30 premières « missions » sont gratuites + +On a hâte de voir votre prochaine création ! \ No newline at end of file diff --git a/fr/GLOSSARY.md b/fr/GLOSSARY.md index 17c69c4d382..48cb7aaa0d3 100644 --- a/fr/GLOSSARY.md +++ b/fr/GLOSSARY.md @@ -1,3 +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) +L'éditeur de texte est une application qui permet d'écrire et 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) \ No newline at end of file diff --git a/fr/README.md b/fr/README.md index f45ef9780cd..fa8bd482a34 100755 --- a/fr/README.md +++ b/fr/README.md @@ -1,52 +1,51 @@ # 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) +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) -> 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/ +> Cette œuvre est mise à disposition selon les termes de la Licence Creative Commons Attribution — Partage dans les Mêmes Conditions 4.0 International. Pour obtenir une copie de cette licence, visitez https://creativecommons.org/licenses/by-sa/4.0/deed.fr -## Translation +## Bienvenue -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 +Bienvenue dans le tutoriel Django Girls ! We are happy to see you here :) In this tutorial, we will take you on a journey under the hood of web technologies, offering you a glimpse of all the bits and pieces that need to come together to make the web work as we know it. + +As with all unknown things, this is going to be an adventure - but no worries, since you already worked up the courage to be here, you'll be just fine :) ## 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 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 ? +Have you ever felt that the world is more and more about technology to which you cannot (yet) relate? 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 amusant. -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. +Ce tutoriel ne vous transformera pas magiquement en programmeuse. 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 a 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 ? -À 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 ! +Once you've finished the tutorial, you will have a small working web application: your own blog. We will show you how to put it online, so others will see your work! Ça devrait ressembler plus ou moins à ça : -![Figure 0.1][2] +![Figure 0.1](images/application.png) - [2]: images/application.png +> 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). 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 ! -> 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 ! +OK, [let's start at the beginning…](./how_the_internet_works/README.md) -Alors, [commençons par le commencement...][3] +## Suivre le tutoriel chez soi - [3]: how_the_internet_works/README.md +Il est formidable de participer à un atelier Django Girls, mais nous comprenons qu'il n'est pas toujours facile d'en trouver un. 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. -## À propos et contributions +Dans chaque chapitre couvert se trouve un lien pointant vers la vidéo correspondante. -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]. +## À propos et contributions - [4]: https://djangogirls.org/ - [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md +Ce tutoriel est maintenu par [DjangoGirls](https://djangogirls.org/). 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](https://github.com/DjangoGirls/tutorial/blob/master/README.md). -## Voulez-vous nous aider à traduire le tutoriel dans d'autres langues ? +## Would you like to help us translate the tutorial into other languages? -Pour l'instant, les traductions sont stockées sur la plate-forme crowdin.com dans : +Currently, translations are being kept on crowdin.com platform at: https://crowdin.com/project/django-girls-tutorial -Si votre langue n'est pas sur crowdin, veuillez [ouvrir un ticket][6] avec la langue, pour que nous puissions l'ajouter. - - [6]: https://github.com/DjangoGirls/tutorial/issues/new +If your language is not listed on [crowdin](https://crowdin.com/), please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. \ No newline at end of file diff --git a/fr/SUMMARY.md b/fr/SUMMARY.md index 4eabc020e6f..c2f1697e220 100755 --- a/fr/SUMMARY.md +++ b/fr/SUMMARY.md @@ -1,26 +1,27 @@ # Résumé -* [Introduction](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) -* [Qu'est-ce que Django?](django/README.md) -* [Installation de Django](django_installation/README.md) -* [Votre premier projet Django !](django_start_project/README.md) -* [Les modèles dans Django](django_models/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) -* [La suite ?](whats_next/README.md) \ No newline at end of file +* [Introduction](README.md) +* [Installation](installation/README.md) +* [Installation (chromebook)](chromebook_setup/README.md) +* [Comment marche 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) +* [Qu'est-ce que Django?](django/README.md) +* [Installation de Django](django_installation/README.md) +* [Votre premier projet Django !](django_start_project/README.md) +* [Les modèles dans Django](django_models/README.md) +* [Django admin](django_admin/README.md) +* [Déployer!](deploy/README.md) +* [Les urls Django](django_urls/README.md) +* [Vues Django - C'est l'heure de créer !](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) +* [La suite?](whats_next/README.md) \ No newline at end of file diff --git a/fr/chromebook_setup/README.md b/fr/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/fr/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/fr/chromebook_setup/instructions.md b/fr/chromebook_setup/instructions.md new file mode 100644 index 00000000000..02f8e89ae54 --- /dev/null +++ b/fr/chromebook_setup/instructions.md @@ -0,0 +1,60 @@ +Vous pouvez [passer cette section](http://tutorial.djangogirls.org/en/installation/#install-python) si vous n'utilisez pas un Chromebook. Si c'est le cas, votre expérience sera un peu différente. Vous pouvez ignorer le reste des instructions d'installation. + +### 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 the software. Pour la durée du tutoriel, Cloud 9 agira comme votre *machine locale*. Vous lancerez toujours des commandes dans un terminal exactement comme vos camarades sous OS X, Ubuntu ou Windows, mais votre terminal sera connecté à un ordinateur autre part que Cloud 9 a configuré pour vous. + +1. Installez Cloud 9 depuis le [Chrome Web Store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Allez à [c9.io](https://c9.io) +3. Créez un compte +4. Click *Create a New Workspace* +5. Appelez-le *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 your instructions. You can resize that window to make it a bit bigger. + +### Environnement virtuel + +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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.0 + + +(note that on the last line we use a tilde followed by an equal sign: ~=). + +### Github + +Créez un compte [Github](https://github.com). + +### 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). \ No newline at end of file diff --git a/fr/code_editor/README.md b/fr/code_editor/README.md index b149081182d..496838b87a5 100755 --- a/fr/code_editor/README.md +++ b/fr/code_editor/README.md @@ -1,7 +1,11 @@ # L'éditeur de texte +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. + Vous allez bientôt écrire vos premières lignes de code : Il vous faut tout d'abord télécharger un éditeur de texte ! -> **Note** : Vous l'avez peut-être déjà fait dans le chapitre d'installation. Si c'est le cas, passez directement au prochain chapitre! +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **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" %} \ No newline at end of file diff --git a/fr/code_editor/instructions.md b/fr/code_editor/instructions.md index d5649f6293b..14aeb7ce91d 100644 --- a/fr/code_editor/instructions.md +++ b/fr/code_editor/instructions.md @@ -1,6 +1,6 @@ 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. +Nos suggestions sont listées ci-dessous, mais n'hésitez pas à demander à vos coachs quelles sont ses préférences - il sera plus facile d'obtenir de l'aide de leur part. ## Gedit @@ -10,13 +10,13 @@ Gedit est un éditeur libre et gratuit disponible pour tout les systèmes d'expl ## 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. +Sublime Text is a very popular editor with a free evaluation period and it's available for all operating systems. [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. +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source and available for Windows, OS X and Linux. [Télécharger](https://atom.io/) @@ -24,8 +24,8 @@ Atom est un éditeur très récent créé par [GitHub](https://github.com/). Dis 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). +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). -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. +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. -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 :) +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. :) \ No newline at end of file diff --git a/fr/css/README.md b/fr/css/README.md index 31e3302fa4b..a75f2ca9dca 100755 --- a/fr/css/README.md +++ b/fr/css/README.md @@ -1,112 +1,115 @@ -# CSS - Rendez votre site joli ! +# CSS – make it pretty! 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, 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 ;) +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. ;) -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. +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. ## 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 : https://getbootstrap.com/ +Bootstrap is one of the most popular HTML and CSS frameworks for developing beautiful websites: https://getbootstrap.com/ -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. +Il a été créé par d'anciens programmeurs·ses de chez Twitter. Il 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`) : +To install Bootstrap, you need to add this to your `` in your `.html` file: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```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à ! - -![Figure 14.1][1] +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! - [1]: images/bootstrap1.png +![Figure 14.1](images/bootstrap1.png) C'est déjà un peu mieux ! ## Les fichiers statiques dans Django -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. +Enfin, allons jeter un coup d'œil à ces **fichiers statiques** dont nous n'arrêtons pas de vous parler. Les fichiers statiques correspondent à tous vos CSS et vos images. Leur contenu ne dépend pas du contexte de la requête et sera le même pour tous les utilisateurs. ### Où ranger 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`. +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`. -Pour cela, nous allons créer un dossier appelé `static` à l'intérieur de notre blog app : +Pour cela, nous allons créer un fichier appelé `static` à l'intérieur de notre blog app : djangogirls ├── blog │ ├── migrations - │ └── static + │ ├── static + │   └── templates └── mysite + - -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. +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. ## 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ête ? +Let's create a CSS file now, to add your own style to your web page. 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 ? djangogirls └─── blog └─── static └─── css └─── blog.css - + Et c'est parti pour un peu de CSS ! Ouvrez le fichier `static/css/blog.css` dans votre éditeur de texte. -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. - - [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`. +We won't be going too deep into customizing and learning about CSS here. There is a recommendation for a free CSS course at the end of this page if you would like to learn more. - [3]: http://www.w3schools.com/cssref/css_colornames.asp +Que pourrions-nous faire rapidement ? Pourquoi ne pas changer la couleur de notre en-tête ? Pour indiquer la couleur que nous souhaitons utiliser, nous devons utiliser un code particulier. 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/. Vous pouvez aussi utiliser des [couleurs prédéfinies](http://www.w3schools.com/colors/colors_names.asp), comme le `rouge` et le `vert`. Ajoutez le code suivant dans votre fichier `blog/static/css/blog.css` : +{% filename %}blog/static/css/blog.css{% endfilename %} + ```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 ! +`h1 a` est un sélecteur CSS. 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. 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` : +Un fichier CSS permet de déterminer le style des éléments présents dans un fichier HTML. 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 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. 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 ``` -Nous vous conseillons d'en apprendre un peu plus sur les sélecteurs CSS sur [w3schools][4]. +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). - [4]: http://www.w3schools.com/cssref/css_selectors.asp +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: -Afin que nos modifications fonctionnent, nous devons aussi signaler à notre template HTML que nous utilisons des CSS. Ouvrez le fichier `blog/templates/blog/post_list.html` et ajoutez cette ligne au tout début de celui-ci : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```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 : +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 ``` -Nous venons simplement de dire à notre template où nous avons rangé notre fichier CSS. +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 be overriden by code in Bootstrap files. Nous venons simplement de dire à notre template où nous avons rangé notre fichier CSS. Maintenant, votre fichier doit ressembler à ceci : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html {% load staticfiles %} @@ -132,35 +135,37 @@ Maintenant, votre fichier doit ressembler à ceci : ``` -Ok, on sauvegarde et on rafraichit la page ! - -![Figure 14.2][5] +Ok, on sauvegarde et on rafraîchit la page ! - [5]: images/color2.png +![Figure 14.2](images/color2.png) Bravo ! Peut-être que nous pourrions un peu aérer notre page web en augmentant la marge du côté gauche ? Essayons pour voir ! +{% filename %}blog/static/css/blog.css{% endfilename %} + ```css body { padding-left: 15px; } ``` -Ajoutez ceci à votre fichier CSS, sauvegardez-le et voyons le résultat ! +Add that to your CSS, save the file and see how it works! -![Figure 14.3][6] - - [6]: images/margin2.png +![Figure 14.3](images/margin2.png) 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` : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html - + ``` -Cette ligne nous permet d'importer la police de caractères *Lobster* depuis 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). + +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: -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. +{% filename %}blog/static/css/blog.css{% endfilename %} ```css h1 a { @@ -169,24 +174,26 @@ h1 a { } ``` -![Figure 14.3][7] - - [7]: images/font.png +![Figure 14.3](images/font.png) Super ! -Comme nous l'avions mentionné précédemment, il existe une notion de classe dans CSS. En gros, cela vous permet de donner un nom à un morceau de code HTML auquel vous souhaitez appliquer un style particulier sans que cela ne concerne le reste du code. C'est particulièrement pratique lorsque vous avez deux divs qui font quelque chose de différent (par exemple, votre entête et votre post) et que vous ne voulez pas qu'ils soient identiques. +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. 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 : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html - ``` +``` Maintenant, ajoutez la classe `post` à votre `div` contenant votre blog post. +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html

published: {{ post.published_date }}

@@ -195,7 +202,9 @@ Maintenant, ajoutez la classe `post` à votre `div` contenant votre blog post.
``` -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` : +Nous allons maintenant ajouter des blocs déclaratifs à différents sélecteurs. Les sélecteurs qui commencent par `.` sont reliés aux classes. There are many great tutorials and explanations about CSS on the Web that can help you understand the following code. Pour l'instant, copier-coller le code qui suit dans votre fichier `blog/static/css/blog.css` : + +{% filename %}blog/static/css/blog.css{% endfilename %} ```css .page-header { @@ -219,7 +228,6 @@ h1, h2, h3, h4 { } .date { - float: right; color: #828282; } @@ -247,7 +255,9 @@ h1, h2, h3, h4 { } ``` -Nous allons maintenant nous intéresser au code concernant les posts. Il va falloir remplacer le code suivant : +Nous allons maintenant nous intéresser au code concernant les posts. Il va falloir remplacer le code le code suivant : + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% for post in posts %} @@ -261,6 +271,8 @@ Nous allons maintenant nous intéresser au code concernant les posts. Il va fall Ce code se trouve dans le fichier `blog/templates/blog/post_list.html`. Il doit être remplacé par le code suivant : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html
@@ -268,7 +280,7 @@ Ce code se trouve dans le fichier `blog/templates/blog/post_list.html`. Il doit {% for post in posts %}
- {{ post.published_date }} +

published: {{ post.published_date }}

{{ post.title }}

{{ post.text|linebreaksbr }}

@@ -279,16 +291,14 @@ Ce code se trouve dans le fichier `blog/templates/blog/post_list.html`. Il doit
``` -Sauvegardez les fichiers modifiés et rafraichissez votre site web. - -![Figure 14.4][8] +Sauvegardez les fichiers modifiés et rafraîchissez votre site web. - [8]: images/final.png +![Figure 14.4](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 saisir l'essentiel rien qu'en le lisant (ce n'est pas grave si ce n'est pas le cas ! ). +Woohoo! Looks awesome, right? Look at the code we just pasted to find the places where we added classes in the HTML and used them in the CSS. Where would you make the change if you wanted the date to be turquoise? -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 ! +Don't be afraid to tinker with this CSS a little bit and try to change some things. Playing with the CSS can help you understand what the different things are doing. If you break something, don't worry – you can always undo it! -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 ! +We really recommend taking this free online [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web). It can help you learn all about making your websites prettier with CSS. -Prête pour le chapitre suivant ? :) +Prête pour le chapitre suivant ? :) \ No newline at end of file diff --git a/fr/deploy/README.md b/fr/deploy/README.md index bc8fdb9c988..7292ef46b63 100755 --- a/fr/deploy/README.md +++ b/fr/deploy/README.md @@ -1,26 +1,18 @@ -# Déployer ! +# Déployer! > **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 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 :). +Until now, your website was only available on your computer. Now you will learn how to deploy it! 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 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. +Comme vous l'avez appris, un site web a besoin d'être installé sur un serveur. There are a lot of server providers available on the internet, we're going to use [PythonAnywhere](https://www.pythonanywhere.com/). PythonAnywhere is free for small applications that don't have too many visitors so it'll definitely be enough for you now. - [1]: https://pythonanywhere.com/ +Nous allons aussi utiliser les services [GitHub](https://www.github.com), 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 ! -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 ! - - [2]: https://www.github.com - -Github va nous servir d'intermédiaire pour envoyer et récupérer notre code sur PythonAnywhere. +These three places will be important to you. Your local computer will be the place where you do development and testing. When you're happy with the changes, you will place a copy of your program on GitHub. Your website will be on PythonAnywhere and you will update it by getting a new copy of your code from GitHub. # Git -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. - -## Installer Git - -> **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. +> **Note** If you already did the Installation steps, there's no need to do this again – you can skip to the next section and start creating your Git repository. {% include "/deploy/install_git.md" %} @@ -28,53 +20,61 @@ Git est un "gestionnaire de version" utilisé par de nombreux·ses développeurs 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 : -> **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`. +> **Note** Check your current working directory with a `pwd` (Mac OS X/Linux) or `cd` (Windows) command before initializing the repository. Vous devriez vous trouver dans le dossier `djangogirls`. + +{% filename %}command-line{% endfilename %} $ 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 + - -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. +Initializing the git repository is something we need to do only once per project (and you won't have to re-enter the username and email ever again). 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 : -``` -*.pyc -__pycache__ -myvenv -db.sqlite3 -/static -.DS_Store -``` +{% filename %}.gitignore{% endfilename %} -Enregistrez ce fichier `.gitignore` dans votre répertoire principal "djangogirls". + *.pyc + *~ + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + -> **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! +And save it as `.gitignore` in the "djangogirls" folder. -> **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. +> **Attention** : le point au début du nom du fichier est important ! If you're having any difficulty creating it (Macs don't like you to create files that begin with a dot via the Finder, for example), then use the "Save As" feature in your editor; it's bulletproof. +> +> **Note** One of the files you specified in your `.gitignore` file is `db.sqlite3`. That file is your local database, where all of your posts are stored. We don't want to add this to your repository because your website on PythonAnywhere is going to be using a different database. That database could be SQLite, like your development machine, but usually you will use one called MySQL which can deal with a lot more site visitors than SQLite. Either way, by ignoring your SQLite database for the GitHub copy, it means that all of the posts you created so far are going to stay and only be available locally, but you're going to have to add them again on production. You should think of your local database as a good playground where you can test different things and not be afraid that you're going to delete your real posts from your blog. -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 : +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`. This will help prevent any surprises from happening, such as wrong files being added or committed. The `git status` command returns information about any untracked/modified/staged files, the branch status, and much more. The output should be similar to the following: + +{% filename %}command-line{% endfilename %} $ 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) - + 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 : +{% filename %}command-line{% endfilename %} + $ git add --all . $ git commit -m "My Django Girls app, first commit" [...] @@ -82,183 +82,154 @@ Pour le moment, nous n'avons fait que regarder l'état de notre branche. Pour en create mode 100644 .gitignore [...] create mode 100644 mysite/wsgi.py - - -## Publier votre code sur GitHub - -Allez sur [GitHub.com][2] et inscrivez-vous gratuitement (si vous possédez déjà un compte, c'est très bien!) - -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. - -![][3] - - [3]: images/new_github_repo.png - -> **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. - -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 : - -![][4] - - [4]: images/github_get_repo_url_screenshot.png - -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. - -Tapez les instructions suivantes dans votre console (remplacez `` avec le nom d'utilisateur de votre compte GitHub et sans les chevrons) : - - $ git remote add origin https://github.com//my-first-blog.git - $ git push -u origin master - - -Entrez votre nom d'utilisateur et mot de passe Github. Vous devriez voir quelque chose comme ceci : - - 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. - - - - -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 :) - - [5]: https://github.com/django/django - [6]: https://github.com/DjangoGirls/tutorial - -# Mettre votre blog en ligne avec PythonAnywhere - -> **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. - -{% include "/deploy/signup_pythonanywhere.md" %} - -## Récupérer votre code sur PythonAnywhere - -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.11.0 - Collecting django - [...] - Successfully installed django-1.11 - - -> **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 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 - -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. - -> **Note** : N'oubliez pas de mettre votre nom d'utilisateur. Ne vous inquiétez pas : si vous faites une erreur, PythonAnywhere vous le signalera. - -### Configurer le fichier WSGI - -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. - -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. - -Supprimer le contenu du fichier et le remplacer par ce qui suit : - -```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 django.contrib.staticfiles.handlers import StaticFilesHandler -application = StaticFilesHandler(get_wsgi_application()) -``` - -> **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. - -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. - -`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. + ``` + + + ## Pushing your code to GitHub + + Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. (If you already did that in the workshop prep, that is great!) + + Then, create a new repository, giving it the name "my-first-blog". Leave the "initialize with a README" checkbox unchecked, leave the .gitignore option blank (we've done that manually) and leave the License as None. + + + + > **Note** The name `my-first-blog` is important – you could choose something else, but it's going to occur lots of times in the instructions below, and you'd have to substitute it each time. It's probably easier to just stick with the name `my-first-blog`. + + On the next screen, you'll be shown your repo's clone URL. Choose the "HTTPS" version, copy it, and we'll paste it into the terminal shortly: + + + + Now we need to hook up the Git repository on your computer to the one up on GitHub. + + Type the following into your console (Replace `` with the username you entered when you created your GitHub account, but without the angle-brackets): + + {% filename %}command-line{% endfilename %} + + +$ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master + +
Enter your GitHub username and password and you should see something like this: + + {% filename %}command-line{% endfilename %} + + +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/hjwp/my-first-blog.git + +- [new branch] master -> master Branch master set up to track remote branch master from origin. + +
<!--TODO: maybe do ssh keys installs in install party, and point ppl who dont have it to an extension --> + + Your code is now on GitHub. Allez jeter un coup d’œil ! You'll find it's in fine company – [Django](https://github.com/django/django), the [Django Girls Tutorial](https://github.com/DjangoGirls/tutorial), and many other great open source software projects also host their code on GitHub. :) + + + # Setting up our blog on PythonAnywhere + + > **Note** You might have already created a PythonAnywhere account earlier during the install steps – if so, no need to do it again. + + {% include "/deploy/signup_pythonanywhere.md" %} + + + ## Pulling our code down on PythonAnywhere + + When you've signed up for PythonAnywhere, you'll be taken to your dashboard or "Consoles" page. Choose the option to start a "Bash" console – that's the PythonAnywhere version of a console, just like the one on your computer. + + <img src="images/pythonanywhere_bash_console.png" alt="pointing at Other: Bash in Start a new Console" /> + + > **Note** PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer. + + Importons notre code depuis Github vers PythonAnywhere en créant un "clone" de notre déôpt. Type the following into the console on PythonAnywhere (don't forget to use your GitHub username in place of `<your-github-username>`): + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ git clone https://github.com//my-first-blog.git + +
This will pull down a copy of your code onto PythonAnywhere. Check it out by typing `tree my-first-blog`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ 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 + +

### Creating a virtualenv on PythonAnywhere + + Just like you did on your own computer, you can create a virtualenv on PythonAnywhere. In the Bash console, type: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +$ cd my-first-blog + +$ virtualenv --python=python3.6 myvenv Running virtualenv with interpreter /usr/bin/python3.6 [...] Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(myvenv) $ pip install django~=1.11.0 Collecting django [...] Successfully installed django-1.11.3 + +

> **Note** The `pip install` step can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach. + + <!--TODO: think about using requirements.txt instead of pip install.--> + + ### Creating the database on PythonAnywhere + + Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer. + + Just as we did on your own computer, we repeat the step to initialize the database on the server, with `migrate` and `createsuperuser`: + + {% filename %}PythonAnywhere command-line{% endfilename %} + + +(mvenv) $ python manage.py migrate Operations to perform: [...] Applying sessions.0001_initial... OK (mvenv) $ python manage.py createsuperuser + +
## Publishing our blog as a web app + + Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app! + + Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the **Web** tab. Finally, hit **Add a new web app**. + + After confirming your domain name, choose **manual configuration** (N.B. – *not* the "Django" option) in the dialog. Next choose **Python 3.6**, and click Next to finish the wizard. + + > **Note** Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-) + + + ### Setting the virtualenv + + You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server. + + <img src="images/pythonanywhere_web_tab_virtualenv.png" /> + + In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter `/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/`. Click the blue box with the checkmark to save the path before moving on. + + > **Note** Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning. + + + ### Configuring the WSGI file + + Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file. + + Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like `/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py`), and you'll be taken to an editor. + + Delete all the contents and replace them with the following: + + {% filename %}<your-username>_pythonanywhere_com_wsgi.py{% endfilename %} + ```python + import os + import sys + + path = os.path.expanduser('~/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 django.contrib.staticfiles.handlers import StaticFilesHandler + application = StaticFilesHandler(get_wsgi_application()) + + +This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is. + +The `StaticFilesHandler` is for dealing with our CSS. This is taken care of automatically for you during local development by the `runserver` command. Pour le moment, vous n'avez pas besoin d'en savoir plus ! Ne vous inquiétez pas : nous reviendrons plus tard sur les fichiers statiques (partie CSS). L'objectif de ce chapitre est de poser toutes les bases nécessaires au déploiement pour passer rapidement à la suite :) Cliquez sur **Save** puis, retournez dans l'onglet **Web**. @@ -266,26 +237,24 @@ Et voilà, c'est fini ! Vous n'avez plus qu'à cliquer sur le gros bouton vert * ## Conseils en cas de bug -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: - - [8]: https://www.pythonanywhere.com/web_app_setup/ +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](https://www.pythonanywhere.com/web_app_setup/) 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: -* 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 et enfin créer la base de données. +- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database. -* 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. +- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem. -* 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"? +- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right? -* Se tromper de version de Python : votre environnement virtuel et votre application web doivent toutes les deux être sous Python 3.4. +- Se tromper de version de Python : votre environnement virtuel et votre application web doivent toutes les deux être sous Python 3.6. -* Il y a quelques [astuces générales de débogage sur le wiki PythonAnywhere][9]. - - [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError +There are also some [general debugging tips on the PythonAnywhere wiki](https://www.pythonanywhere.com/wiki/DebuggingImportError). Et n'oubliez pas, votre coach est là pour vous aider ! # Votre site est en ligne ! -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. +The default page for your site should say "It worked!", just like it does on your local computer. 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. + +Once you have a few posts created, you can go back to your local setup (not PythonAnywhere). From here you should work on your local setup to make changes. This is a common workflow in web development – make changes locally, push those changes to GitHub, and pull your changes down to your live Web server. This allows you to work and experiment without breaking your live Web site. Pretty cool, huh? -*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 +*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 \ No newline at end of file diff --git a/fr/deploy/install_git.md b/fr/deploy/install_git.md index 2190df46aa8..3d951a58254 100644 --- a/fr/deploy/install_git.md +++ b/fr/deploy/install_git.md @@ -1,17 +1,52 @@ -### Windows +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. -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. +## Installer Git -### MacOS + + +Vous pouvez télécharger Git sur [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). 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. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + 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 +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} -Git est probablement déjà installé mais, si ce n'est pas le cas, voici les instructions à suivre : +```bash +$ sudo zypper install git +``` - sudo apt-get install git - # ou - sudo yum install git - # ou - sudo zypper install git \ No newline at end of file + \ No newline at end of file diff --git a/fr/deploy/signup_pythonanywhere.md b/fr/deploy/signup_pythonanywhere.md index 3b6e7b711a2..ca66bd0de69 100644 --- a/fr/deploy/signup_pythonanywhere.md +++ b/fr/deploy/signup_pythonanywhere.md @@ -1,5 +1,5 @@ -Si vous ne l'avez pas encore fait, n'oubliez pas de vous créer un compte "Beginner" sur PythonAnywhere. +Next, it's time to sign up for a free "Beginner" account on PythonAnywhere. - * [www.pythonanywhere.com](https://www.pythonanywhere.com/) +* [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 +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname or a name for what your blog is all about. \ No newline at end of file diff --git a/fr/django/README.md b/fr/django/README.md index b11204e524e..3a3c4fe37ca 100755 --- a/fr/django/README.md +++ b/fr/django/README.md @@ -1,27 +1,27 @@ # Qu'est-ce que Django? -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. +Django (/ˈdʒæŋɡoʊ/ *jang-goh*) is a free and open source web application framework, written in Python. Un framework web est un ensemble de composants qui vous aide à développer des sites web plus rapidement et plus facilement. 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 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. +Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use. -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. +Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site. ## Pourquoi est-ce que vous auriez besoin d'un framework ? -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. +To understand what Django is actually for, we need to take a closer look at the servers. The first thing is that the server needs to know that you want it to serve you a web page. -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. +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. The web server reads the letter and then sends a response with a webpage. 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. ## 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)*). +When a request comes to a web server, it's passed to Django which tries to figure out what is actually requested. It takes a web page address first and tries to figure out what to do. This part is done by Django's **urlresolver** (note that a website address is called a URL – Uniform Resource Locator – so the name *urlresolver* makes sense). It is not very smart – it takes a list of patterns and tries to match the URL. Django checks patterns from top to bottom and if something is matched, then Django passes the request to the associated function (which is called *view*). 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 : 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. +In the *view* function, all the interesting things are done: we can look at a database to look for some information. Par exemple, peut-être que l'utilisateur vient de demander de changer quelque chose dans ces données ? Like a letter saying, "Please change the description of my job." The *view* can check if you are allowed to do that, then update the job description for you and send back a message: "Done!" Then the *view* generates a response and Django can send it to the user's web browser. 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 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 ? +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 ? \ No newline at end of file diff --git a/fr/django_admin/README.md b/fr/django_admin/README.md index 3653cfc4d60..f31f0cd9851 100755 --- a/fr/django_admin/README.md +++ b/fr/django_admin/README.md @@ -1,48 +1,57 @@ -# L'interface d'administration de Django +# Django admin -Pour ajouter, éditer et supprimer les posts que nous venons de modéliser, nous allons utiliser l'interface d'administration de Django. +To add, edit and delete the posts we've just modeled, we will use Django admin. -Ouvrons le fichier `blog/admin.py` et remplaçons son contenu par ceci : +Let's open the `blog/admin.py` file and replace its contents with this: + +{% filename %}blog/admin.py{% endfilename %} ```python 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)`. -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: +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. Go to your browser and type the address http://127.0.0.1:8000/admin/. Vous verrez une page de login qui ressemble à celle-ci : + +![Page de login](images/login_page2.png) -![Page de login][1] +To log in, you need to create a *superuser* - a user account that has control over everything on the site. Go back to the command line, type `python manage.py createsuperuser`, and press enter. - [1]: images/login_page2.png +> Remember, to write new commands while the web server is running, open a new terminal window and activate your virtualenv. We reviewed how to write new commands in the **Your first Django project!** chapter, in the **Starting the web server** section. -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. +{% filename %}Mac OS X or Linux:{% endfilename %} (myvenv) ~/djangogirls$ python manage.py createsuperuser + + +{% filename %}Windows:{% endfilename %} + + (myvenv) C:\Users\Name\djangogirls> python manage.py createsuperuser + + +When prompted, type your username (lowercase, no spaces), email address, and password. **Don't worry that you can't see the password you're typing in – that's how it's supposed to be.** Just type it in and press `enter` to continue. The output should look like this (where the username and email should be your own ones): + Username: admin Email address: admin@admin.com Password: Password (again): Superuser created successfully. + +Return to your browser. Log in with the superuser's credentials you chose; you should see the Django admin dashboard. -Retournez dans votre navigateur et connectez-vous en tant que superutilisateur grâce à l'utilisateur que vous venez de créer. Vous devriez accéder à l'interface d'administration de Django. - -![Django admin][2] - - [2]: images/django_admin3.png - -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 :). +![Django admin](images/django_admin3.png) -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. +Go to Posts and experiment a little bit with it. Add five or six blog posts. Don't worry about the content – you can simply copy-paste some text from this tutorial to save time. :) -![Django admin][3] +Make sure that at least two or three posts (but not all) have the publish date set. It will be helpful later. - [3]: images/edit_post3.png +![Django admin](images/edit_post3.png) -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.11/ref/contrib/admin/ +If you want to know more about Django admin, you should check Django's documentation: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ -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 ! +This is probably a good moment to grab a coffee (or tea) or something to eat to re-energize yourself. You created your first Django model – you deserve a little break! \ No newline at end of file diff --git a/fr/django_forms/README.md b/fr/django_forms/README.md index fbfd803d507..494c06e426d 100755 --- a/fr/django_forms/README.md +++ b/fr/django_forms/README.md @@ -1,6 +1,6 @@ # Formulaires Django -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 ! +La dernière chose que nous voulons faire sur notre site web, c'est 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. With `forms` we will have absolute power over our interface – we can do almost anything we can imagine! 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. @@ -12,9 +12,11 @@ Nous allons devoir créer un fichier avec ce nom dans notre dossier `blog`. blog └── forms.py + +OK, let's open it and type the following code: -Ouvrez maintenant ce fichier et tapez le code suivant : +{% filename %}blog/forms.py{% endfilename %} ```python from django import forms @@ -30,27 +32,31 @@ class PostForm(forms.ModelForm): 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`. +Comme vous l'avez probablement deviné, `PostForm` est le nom de notre formulaire. We need to tell Django that this form is a `ModelForm` (so Django will do some magic for us) – `forms.ModelForm` is responsible for that. 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 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). +Enfin, nous précisions quels sont le⋅s champ⋅s qui doivent figurer dans notre formulaire. In this scenario we want only `title` and `text` to be exposed – `author` should be the person who is currently logged in (you!) and `created_date` should be automatically set when we create a post (i.e. in the code), right? 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. -Nous allons donc une nouvelle fois suivre le processus suivant et créer : un lien vers la page, une URL, une vue et un template. +So once again we will create a link to the page, a URL, a view and a template. ## Lien vers une page contenant le formulaire C'est le moment d'ouvrir le fichier `blog/templates/blog/base.html`. Nous allons ajouter un lien dans un `div` appelé `page-header` : +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html ``` -Remarquez que notre nouvelle vue s'appelle `post_new`. +Note that we want to call our new view `post_new`. The class `"glyphicon glyphicon-plus"` is provided by the bootstrap theme we are using, and will display a plus sign for us. + +After adding the line, your HTML file should now look like this: -Après avoir ajouté cette ligne, votre fichier html devrait maintenant ressembler à ceci : +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% load staticfiles %} @@ -79,40 +85,48 @@ Après avoir ajouté cette ligne, votre fichier html devrait maintenant ressembl ``` -Sauvegardez votre fichier et rafraichissez la page http://127.0.0.1:8000 : vous devez normalement tomber encore une fois sur l'erreur `NoReverseMatch` ! +Sauvegardez votre fichier et rafraîchissez 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 : +{% filename %}blog/urls.py{% endfilename %} + ```python - url(r'^post/new/$', views.post_new, name='post_new'), +url(r'^post/new/$', views.post_new, name='post_new'), ``` Votre fichier doit maintenant ressembler à ceci : +{% filename %}blog/urls.py{% endfilename %} + ```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/(?P\d+)/$', 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. Nous n'avons pas encore implémentée la vue `post_new`. Allons nous occuper de ça maintenant. +After refreshing the site, we see an `AttributeError`, since we don't have the `post_new` view implemented. Let's add it right now. ## La vue post_new Ouvrez maintenant le fichier `blog/views.py` et ajoutez les lignes suivantes avec celles du `from` qui existent déjà : +{% filename %}blog/views.py{% endfilename %} + ```python from .forms import PostForm ``` -Puis ajoutez la *vue* : +And then our *view*: + +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): @@ -120,22 +134,22 @@ def post_new(request): 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. +Afin de pouvoir créer un nouveau formulaire `Post`, nous avons besoin d'appeler la fonction `PostForm()` et de la passer au template. We will go back to this *view*, but for now, let's quickly create a template for the form. ## Template 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 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 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 : +* We have to display the form. We can do that with (for example) {% raw %}`{{ form.as_p }}`{% endraw %}. +* The line above needs to be wrapped with an HTML form tag: `...
`. +* We need a `Save` button. We do that with an HTML button: ``. +* And finally, just after the opening `
` tag we need to add {% raw %}`{% csrf_token %}`{% endraw %}. C'est très important car c'est ce qui va permettre de sécuriser votre formulaire ! If you forget about this bit, Django will complain when you try to save the form: -![CSFR Forbidden page][1] +![CSFR Forbidden page](images/csrf2.png) - [1]: images/csrf2.png +OK, so let's see how the HTML in `post_edit.html` should look: -Ok, voyons maintenant à quoi devrait ressembler le fichier `post_edit.html` : +{% filename %}blog/templates/blog/post_edit.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -149,21 +163,21 @@ Ok, voyons maintenant à quoi devrait ressembler le fichier `post_edit.html` : {% endblock %} ``` -Rafraichissons la page ! Et voilà : le formulaire s'affiche ! +Rafraîchissons la page ! Et voilà : le formulaire s'affiche ! -![Nouveau formulaire][2] +![Nouveau formulaire](images/new_form2.png) - [2]: images/new_form2.png +But, wait a minute! When you type something in the `title` and `text` fields and try to save it, what will happen? -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éé. Que s'est-il passé ? +Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong? La réponse est : rien ! Nous avons juste encore un peu de travail à accomplir. Retournons à notre *vue*. ## Sauvegarder le contenu du formulaire -Ouvrez à nouveau `blog/views.py`. Actuellement, `post_new` n'est composé que des lignes de code suivantes : +Open `blog/views.py` once again. Currently all we have in the `post_new` view is the following: + +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): @@ -171,9 +185,11 @@ def post_new(request): return render(request, 'blog/post_edit.html', {'form': form}) ``` -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. +When we submit the form, we are brought back to the same view, but this time we have some more data in `request`, more specifically in `request.POST` (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data). Remember how in the HTML file, our `` definition had the variable `method="POST"`? 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). +So in our *view* we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the *view* with all form data we just typed. Pour gérer ces deux cas, nous allons utiliser une condition `if` (si): + +{% filename %}blog/views.py{% endfilename %} ```python if request.method == "POST": @@ -182,41 +198,51 @@ else: form = PostForm() ``` -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 : +It's time to fill in the dots `[...]`. If `method` is `POST` then we want to construct the `PostForm` with data from the form, right? We will do that as follows: + +{% filename %}blog/views.py{% endfilename %} ```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 soient bien remplis et qu'aucune donnée incorrecte ne soit sauvegardée. Pour cela, nous allons utiliser `form.is_valid()`. +The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with `form.is_valid()`. Testons donc si notre formulaire est valide et, si c'est le cas, sauvegardons-le ! +{% filename %}blog/views.py{% endfilename %} + ```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 d'un auteur pour que le formulaire que nous avons créé soit valide). `commit=False` means that we don't want to save the `Post` model yet – we want to add the author first. Most of the time you will use `form.save()` without `commit=False`, but in this case, we need to supply it. `post.save()` will preserve changes (adding the author) and a new blog post is created! -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éé ! +Finally, it would be awesome if we could immediately go to the `post_detail` page for our newly created blog post, right? To do that we need one more 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 : +{% filename %}blog/views.py{% endfilename %} ```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éé". +Add it at the very beginning of your file. And now we can say, "go to the `post_detail` page for the newly created post": + +{% filename %}blog/views.py{% endfilename %} ```python return redirect('post_detail', pk=post.pk) ``` -`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éé ! +`post_detail` is the name of the view we want to go to. Rappelez-vous : une *vue* a besoin d'une variable `pk`. To pass it to the views, we use `pk=post.pk`, where `post` is the newly created blog post! + +OK, we've talked a lot, but we probably want to see what the whole *view* looks like now, right? -Et si au lieu de parler, nous vous montrions à quoi ressemble maintenant notre *vue* ? +{% filename %}blog/views.py{% endfilename %} ```python def post_new(request): @@ -233,41 +259,41 @@ def post_new(request): return render(request, 'blog/post_edit.html', {'form': form}) ``` -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` ! +Voyons si ça marche. Go to the page http://127.0.0.1:8000/post/new/, add a `title` and `text`, save it… and voilà! The new blog post is added and we are redirected to the `post_detail` page! -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). +You might have noticed that we are setting the publish date before saving the post. Later on, we will introduce a *publish button* in **Django Girls Tutorial: Extensions**. Encore bravo ! -## Validation de formulaire - -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. +> As we have recently used the Django admin interface, the system currently thinks we are still logged in. There are a few situations that could lead to us being logged out (closing the browser, restarting the DB, etc.). If, when creating a post, you find that you are getting errors referring to the lack of a logged-in user, head to the admin page http://127.0.0.1:8000/admin and log in again. 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. -Essayez de sauvegarder un formulaire sans mettre de `titre` ou de `texte`. Devinez ce qui va se passer ! +![Erreur de loggin](images/post_create_error.png) -![Validation de formulaire][3] - - [3]: images/form_validation2.png +## Validation de formulaire -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 ? +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). In our `Post` model we did not say that these fields (as opposed to `published_date`) are not required, so Django, by default, expects them to be set. -> 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. +Try to save the form without `title` and `text`. Guess what will happen! -![Erreur de loggin][4] +![Validation de formulaire](images/form_validation2.png) - [4]: images/post_create_error.png +Django is taking care to validate that all the fields in our form are correct. Isn't it awesome? ## Éditer un formulaire -Maintenant, nous savons comme ajouter un nouveau formulaire. Comment faire si nous voulons éditer un formulaire déjà existant ? C'est assez proche de ce que nous venons de faire. Créons ce dont nous avons besoin rapidement. Si jamais des choses vous semblent obscures, n'hésitez pas à demander à votre coach ou à revoir les chapitres précédents. Tout ce que nous allons faire maintenant a déjà été expliqué plus en détail précédemment. +Maintenant, nous savons comme ajouter un nouveau formulaire. Comment faire si nous voulons éditer un formulaire déjà existant ? This is very similar to what we just did. Let's create some important things quickly. (If you don't understand something, you should ask your coach or look at the previous chapters, since we covered all these steps already.) -Ouvrez le fichier `blog/templates/blog/post_detail.html` et ajoutez la ligne suivante : +Open `blog/templates/blog/post_detail.html` and add the line -```python +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html ``` -Votre template doit ressembler à ceci : +so that the template will look like this: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -288,13 +314,17 @@ Votre template doit ressembler à ceci : Maintenant, dans `blog/urls.py`, ajoutez cette ligne : +{% filename %}blog/urls.py{% endfilename %} + ```python - url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), + url(r'^post/(?P\d+)/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 : +Let's open `blog/views.py` and add this at the very end of the file: + +{% filename %}blog/views.py{% endfilename %} ```python def post_edit(request, pk): @@ -312,47 +342,51 @@ def post_edit(request, pk): 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 : +Vous ne trouvez pas que ça ressemble presque à la vue de `post_new` ? Regardons un peu plus en détails. For one, we pass an extra `pk` parameter from urls. Next, we get the `Post` model we want to edit with `get_object_or_404(Post, pk=pk)` and then, when we create a form, we pass this post as an `instance`, both when we save the form… + +{% filename %}blog/views.py{% endfilename %} ```python form = PostForm(request.POST, instance=post) ``` -Puis ensuite lorsque nous ouvrons le formulaire associé à ce post afin de l'éditer : +…and when we've just opened a form with this post to edit: + +{% filename %}blog/views.py{% endfilename %} ```python form = PostForm(instance=post) ``` -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 : +OK, let's test if it works! Let's go to the `post_detail` page. There should be an edit button in the top-right corner: -![Bouton d'édition][5] - - [5]: images/edit_button2.png +![Bouton d'édition](images/edit_button2.png) Lorsque vous cliquez dessus, vous devez voir le formulaire du post de blog apparaitre : -![Éditer un formulaire][6] - - [6]: images/edit_form2.png +![Éditer un formulaire](images/edit_form2.png) -Essayez de manipuler un peu ce que vous venez de créer : ajoutez du texte, changez le titre puis sauvegardez ces changements ! +Feel free to change the title or the text and save the changes! -Bravo ! Votre application se complexifie et contient de plus en plus de fonctionnalités ! +Bravo ! Votre application se complexifie et contient de plus en plus de fonctionnalité ! -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.11/topics/forms/ +If you need more information about Django forms, you should read the documentation: https://docs.djangoproject.com/en/1.11/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. +C’est génial de pouvoir créer de nouveaux posts juste en cliquant sur un lien ! But right now, anyone who visits your site will be able to make a new blog post, and that's probably not something you want. Let's make it so the button shows up for you but not for anyone else. 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 : +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html ``` -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 : +We're going to add another `{% if %}` tag to this, which will make the link show up only for users who are logged into the admin. Right now, that's just you! Changez la balise `` comme ceci : + +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% if user.is_authenticated %} @@ -360,37 +394,54 @@ On va y ajouter une autre balise `{% if %}` qui ne fera apparaitre le lien qu’ {% 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. +This `{% if %}` will cause the link to be sent to the browser only if the user requesting the page is logged in. 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. + +Remember the edit icon we just added to our detail page? We also want to add the same change there, so other people won't be able to edit existing posts. + +Open `blog/templates/blog/post_detail.html` and find this line: + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html + +``` + +Change it to this: -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 ! +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Since you're likely logged in, if you refresh the page, you won't see anything different. Load the page in a different browser or an incognito window (called "InPrivate" in Windows Edge), though, and you'll see that the link doesn't show up, and the icon doesn't display either! ## Encore un petit effort : déployons ! 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 -``` +* Tout d'abord, commiter votre nouveau code et pusher le à nouveau sur Github: + +{% filename %}command-line{% endfilename %} + $ 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 commit -m "Added views to create/edit blog post inside the site." $ git push -``` + -* Puis, dans la console bash de [PythonAnywhere][7]: +* Puis, dans la console bash de [PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +{% filename %}command-line{% endfilename %} - [7]: https://www.pythonanywhere.com/consoles/ -``` $ cd my-first-blog - $ source myvenv/bin/activate - (myvenv)$ git pull + $ 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/ +* Enfin, cliquez sur l'onglet [Web](https://www.pythonanywhere.com/web_app_setup/) et cliquez sur **Reload**. -Normalement, ça devrait suffire ! Encore bravo :) +Normalement, ça devrait suffire ! Encore bravo :) \ No newline at end of file diff --git a/fr/django_installation/README.md b/fr/django_installation/README.md index c775ee7bbc4..b50d46ce4f1 100755 --- a/fr/django_installation/README.md +++ b/fr/django_installation/README.md @@ -1,5 +1,7 @@ # Installation de Django -> **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 ! +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. +> +> **Note** If you already worked through the Installation steps then you've already done this – you can go straight to the next chapter! {% 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 index 7bc4f86512b..f3729f0a474 100644 --- a/fr/django_installation/instructions.md +++ b/fr/django_installation/instructions.md @@ -1,6 +1,6 @@ -> 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. +> Part of this section is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Part of this section is based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the 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 @@ -8,106 +8,194 @@ Avant d'installer Django, nous allons vous faire installer un outil extrêmement 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). +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. On Windows, it might look like `C:\Users\Name` (where `Name` is the name of your login). + +> **NOTE:** On Windows, make sure that this directory does not contain accented or special characters; if your username contains accented characters, use a different directory, for example, `C:\djangogirls`. Dans ce tutoriel, nous allons utiliser un nouveau dossier `djangogirls` que vous allez créer dans votre dossier home : - mkdir djangogirls - cd djangogirls +{% filename %}command-line{% endfilename %} + $ mkdir djangogirls + $ cd djangogirls + Nous allons créer un virtualenv appelé `myvenv`. Pour cela, nous taperons une commande qui ressemblera à : - python3 -m venv myvenv +{% filename %}command-line{% endfilename %} + + $ python3 -m venv myvenv + + -### Windows +To create a new `virtualenv`, you need to open the command prompt and run `python -m venv myvenv`. It will look like this: -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 : +{% filename %}command-line{% endfilename %} - C:\Utilisateurs\Nom\djangogirls> C:\Python34\python -m venv myvenv + C:\Users\Name\djangogirls> python -m venv myvenv + +Where `myvenv` is the name of your `virtualenv`. Vous pouvez choisir un autre nom mais attention : il doit être en minuscules, sans espaces et sans accents ou caractères spéciaux. It is also good idea to keep the name short – you'll be referencing it a lot! -`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 : +We can create a `virtualenv` on both Linux and OS X by running `python3 -m venv myvenv`. It will look like this: - ~/djangogirls$ python3 -m venv myvenv +{% filename %}command-line{% endfilename %} + $ 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! +`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. It is also a good idea to keep the name short as you'll be referencing it a lot! -> **NOTE:** initialiser un environnement virtuel sous Ubuntu 14.04 de cette manière donne l'erreur suivante : -> +> **NOTE:** On some versions of Debian/Ubuntu you may receive the following error: +> +> {% filename %}command-line{% endfilename %} +> +> The virtual environment was not created successfully because ensurepip is not available. On Debian/Ubuntu systems, you need to install the python3-venv package using the following command. +> apt-get install python3-venv +> You may need to use sudo with that command. After installing the python3-venv package, recreate your virtual environment. +> +> +> In this case, follow the instructions above and install the `python3-venv` package: {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python3-venv +> +> +> **NOTE:** On some versions of Debian/Ubuntu initiating the virtual environment like this currently gives the following error: +> +> {% filename %}command-line{% endfilename %} +> > 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 +> +> {% filename %}command-line{% endfilename %} +> +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.6 myvenv +> +> +> **NOTE:** If you get an error like +> +> {% filename %}command-line{% endfilename %} +> +> E: Unable to locate package python3-venv > +> +> then instead run: +> +> {% filename %}command-line{% endfilename %} +> +> sudo apt install python3.6-venv +> + + ## 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 : +{% filename %}command-line{% endfilename %} + C:\Utilisateurs\Nom\djangogirls> myvenv\Scripts\activate + + +> **NOTE:** on Windows 10 you might get an error in the Windows PowerShell that says `execution of scripts is disabled on this system`. In this case, open another Windows PowerShell with the "Run as Administrator" option. Then try typing the following command before starting your virtual environment: +> +> {% filename %}command-line{% endfilename %} +> +> C:\WINDOWS\system32> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned +> Execution Policy Change +> The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic at http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A +> + -#### Linux et OS X + Démarrez votre environnement virtuel en exécutant : - ~/djangogirls$ source myvenv/bin/activate +{% filename %}command-line{% endfilename %} + $ 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 +> +> {% filename %}command-line{% endfilename %} +> +> $ . myvenv/bin/activate > -Vous saurez que votre `virtualenv` est lancé quand le prompt de votre console ressemblera à ceci : + - (myvenv) C:\Utilisateurs\Nom\djangogirls> +You will know that you have `virtualenv` started when you see that the prompt in your console is prefixed with `(myvenv)`. +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`. -ou : +Ok, nous avons installé toutes les dépendances dont nous avions besoin. Nous allons enfin pouvoir installer Django ! - (myvenv) ~/djangogirls$ +## Installation de Django +Now that you have your `virtualenv` started, you can install Django. -Vous remarquez que le préfixe `(myvenv)` est apparu ! +Before we do that, we should make sure we have the latest version of `pip`, the software that we use to install Django: -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`. +{% filename %}command-line{% endfilename %} -Ok, nous avons installé toutes les dépendances dont nous avions besoin. Nous allons enfin pouvoir installer Django ! + (myvenv) ~$ pip install --upgrade pip + -## Installation de Django +Then run `pip install django~=1.11.0` (note that we use a tilde followed by an equal sign: `~=`) to install Django. -Maintenant que vous avez lancé votre `virtualenv`, vous pouvez installer Django à l'aide de `pip`. Dans votre console, tapez `pip install django~=1.11.0`. Notez bien que nous utilisons un tilde suivi du signe égal : `~=`). +{% filename %}command-line{% endfilename %} (myvenv) ~$ pip install django~=1.11.0 - Downloading/unpacking django==1.11 + Collecting django~=1.11.0 + Downloading Django-1.11.3-py2.py3-none-any.whl (6.8MB) Installing collected packages: django - Successfully installed django - Cleaning up... + Successfully installed django-1.11.3 + + -Sous Windows : +> If you get an error when calling pip on Windows platform, please check if your project pathname contains spaces, accents or special characters (for example, `C:\Users\User Name\djangogirls`). If it does, please consider using another place without spaces, accents or special characters (suggestion: `C:\djangogirls`). Create a new virtualenv in the new directory, then delete the old one and try the above command again. (Moving the virtualenv directory won't work since virtualenv uses absolute paths.) -> 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 : + + +> Your command line might freeze after when you try to install Django. If this happens, instead of the above command use: +> +> {% filename %}command-line{% endfilename %} +> +> C:\Users\Name\djangogirls> python -m pip install django~=1.11.0 +> + + + + > 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 ! + + +Et voilà ! Vous êtes (enfin) prête pour créer votre première application Django ! \ No newline at end of file diff --git a/fr/django_models/README.md b/fr/django_models/README.md index abd14c9209c..882adb3d137 100755 --- a/fr/django_models/README.md +++ b/fr/django_models/README.md @@ -1,40 +1,40 @@ # Les modèles dans Django -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`. +Maintenant, nous aimerions créer quelque chose qui permet stocker les articles de notre blog. Mais avant de pour pouvoir faire ça, nous allons tout d'abord devoir vous parler d'un truc qui s'appelle les `objets`. ## Les objets -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. +There is a concept in programming called `object-oriented programming`. The idea is that instead of writing everything as a boring sequence of programming instructions, we can model things and define how they interact with each other. 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. +If we want to model a cat, we will create an object `Cat` that has some properties such as `color`, `age`, `mood` (like good, bad, or sleepy ;)), and `owner` (which could be assigned a `Person` object – or maybe, in case of a stray cat, this property could be empty). -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`). +Then the `Cat` has some actions: `purr`, `scratch`, or `feed` (in which case, we will give the cat some `CatFood`, which could be a separate object with properties, like `taste`). - Chat + Cat -------- - couleur + color age - humeur - propriétaire - ronronner() - gratter() - nourrir(nourriture_pour_chat) - - - NourriturePourChat + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood -------- - gout - + taste + 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épondre à la question : qu'est-ce qu'un article de blog ? Quelles propriétés devrait-il avoir ? +Pour ça, il faut réponde à la question : qu'est-ce qu'un article de blog ? Quelles propriétés devrait-il avoir ? -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é. +Pour commencer, notre blog post doit avoir du texte : il a bien du contenu et un titre, n'est-ce pas ? It would be also nice to know who wrote it – so we need an author. Enfin, on aimerait aussi savoir quand l'article a été écrit et publié. Post -------- @@ -43,7 +43,7 @@ Pour commencer, notre blog post doit avoir du texte : il a bien du contenu et un author created_date published_date - + 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. @@ -55,7 +55,7 @@ Voilà, nous avons une idée de ce que nous avons besoin. Allons modéliser tout Maintenant que nous savons ce qu'est un objet, nous allons pouvoir créer un modèle Django pour notre post de blog. -Un modèle Django est un type particulier d'objet : il est sauvegardé dans la `database`. Une base de données est une collection de données. C'est à cet endroit que l'on stocke toutes les informations au sujet des utilisateurs, des blog posts, etc. Pour stocker nos données, nous allons utiliser une base de données SQLite. C'est la base de données par défaut dans Django. Elle sera largement suffisante pour ce que nous voulons faire. +A model in Django is a special kind of object – it is saved in the `database`. Une base de données est une collection de données. C'est à cet endroit que l'on stocke toutes les informations au sujet des utilisateurs, des blog posts, etc. Pour stocker nos données, nous allons utiliser une base de données SQLite. This is the default Django database adapter – it'll be enough for us right now. Pour vous aider à visualiser ce qu'est une base de données, pensez à un tableur avec des colonnes (champs) et des lignes (données). @@ -63,29 +63,40 @@ Pour vous aider à visualiser ce qu'est une base de données, pensez à un table 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`) : +{% filename %}Mac OS X and Linux:{% endfilename %} + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +{% filename %}Windows:{% endfilename %} + (myvenv) C:\Users\Name\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 : +You will notice that a new `blog` directory is created and it contains a number of files now. The directories and files in our project should look like this: djangogirls - ├── mysite - | __init__.py - | settings.py - | urls.py - | wsgi.py + ├── blog + │   ├── __init__.py + │   ├── admin.py + │   ├── apps.py + │   ├── migrations + │   │   └── __init__.py + │   ├── models.py + │   ├── tests.py + │   └── views.py + ├── db.sqlite3 ├── manage.py - └── blog - ├── migrations - | __init__.py + └── mysite ├── __init__.py - ├── admin.py - ├── models.py - ├── tests.py - └── views.py + ├── settings.py + ├── urls.py + └── wsgi.py + +After creating an application, we also need to tell Django that it should use it. We do that in the file `mysite/settings.py`. We need to find `INSTALLED_APPS` and add a line containing `'blog',` just above `]`. So the final product should look like this: -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 : +{% filename %}mysite/settings.py{% endfilename %} ```python INSTALLED_APPS = [ @@ -101,9 +112,11 @@ INSTALLED_APPS = [ ### 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. Pour éviter tout problème (les caractères accentués par exemple!), nous allons garder les termes en anglais. +In the `blog/models.py` file we define all objects called `Models` – this is a place in which we will define our blog post. -Ouvrez le fichier `blog/models.py`, supprimez tout ce qui s'y trouve et copiez-y le morceau de code suivant : +Let's open `blog/models.py`, remove everything from it, and write code like this: + +{% filename %}blog/models.py{% endfilename %} ```python from django.db import models @@ -111,7 +124,7 @@ from django.utils import timezone class Post(models.Model): - author = models.ForeignKey('auth.User') + author = models.ForeignKey('auth.User',on_delete=models.CASCADE) title = models.CharField(max_length=200) text = models.TextField() created_date = models.DateTimeField( @@ -127,44 +140,53 @@ class Post(models.Model): 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". +> Double-check that you use two underscore characters (`_`) on each side of `str`. C'est une convention fréquemment utilisée en Python qui porte même un petit nom en anglais : "dunder", pour "double-underscore". + +It looks scary, right? But don't worry – we will explain what these lines mean! -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! +All lines starting with `from` or `import` are lines that add some bits from other files. So instead of copying and pasting the same things in every file, we can include some parts with `from ... import ...`. -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):` – this line defines our model (it is an `object`). -`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` is the name of our model. We can give it a different name (but we must avoid special characters and whitespace). Always start a class name with an uppercase letter. +- `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. -* 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 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. +Now we define the properties we were talking about: `title`, `text`, `created_date`, `published_date` and `author`. To do that we need to define the type of each field (Is it text? A number? A date? A relation to another object, like a User?) -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` – this is how you define text with a limited number of characters. +- `models.TextField` – this is for long text without a limit. Sounds ideal for blog post content, right? +- `models.DateTimeField` – this is a date and time. +- `models.ForeignKey` – this is a link to another model. -* `models.CharField` - Cela nous permet de définir un champ texte avec un nombre limité de caractères. -* `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. +We will not explain every bit of code here since it would take too much time. You should take a look at Django's documentation if you want to know more about Model fields and how to define things other than those described above (https://docs.djangoproject.com/en/1.11/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.11/ref/models/fields/#field-types). +What about `def publish(self):`? This is exactly the `publish` method we were talking about before. `def` means that this is a function/method and `publish` is the name of the method. You can change the name of the method if you want. The naming rule is that we use lowercase and underscores instead of spaces. For example, a method that calculates average price could be called `calculate_average_price`. -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`. +Methods often `return` something. There is an example of that in the `__str__` method. In this scenario, when we call `__str__()` we will get a text (**string**) with a Post title. -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. +Also notice that both `def publish(self):` and `def __str__(self):` are indented inside our class. Because Python is sensitive to whitespace, we need to indent our methods inside the class. Otherwise, the methods won't belong to the class, and you can get some unexpected behavior. -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 ! +If something is still not clear about models, feel free to ask your coach! We know it is complicated, especially when you learn what objects and functions are at the same time. But hopefully it looks slightly less magic for you now! ### 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 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 : +The last step here is to add our new model to our database. First we have to make Django know that we have some changes in our model. (We have just created it!) Go to your console window and type `python manage.py makemigrations blog`. It will look like this: + +{% filename %}command-line{% endfilename %} (myvenv) ~/djangogirls$ python manage.py makemigrations blog Migrations for 'blog': - 0001_initial.py: + blog/migrations/0001_initial.py: + - Create model Post + +**Note:** Remember to save the files you edit. Otherwise, your computer will execute the previous version which might give you unexpected error messages. -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 : +Django prepared a migration file for us that we now have to apply to our database. Type `python manage.py migrate blog` and the output should be as follows: + +{% filename %}command-line{% endfilename %} (myvenv) ~/djangogirls$ python manage.py migrate blog Operations to perform: @@ -172,6 +194,6 @@ Django vient de nous préparer un fichier de migration que nous allons pouvoir a 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 ;)! +Hurray! Our Post model is now in our database! It would be nice to see it, right? Jump to the next chapter to see what your Post looks like! \ No newline at end of file diff --git a/fr/django_orm/README.md b/fr/django_orm/README.md index 9ca9ec4c9dd..82a842d6c72 100755 --- a/fr/django_orm/README.md +++ b/fr/django_orm/README.md @@ -4,7 +4,7 @@ Dans ce chapitre, nous allons apprendre comment Django se connecte à la base de ## Qu'est-ce qu'un QuerySet ? -Un QuerySet est, par essence, une liste d'objets d'un modèle donné. C'est ce qui vous permet de lire, trier et organiser, des données présentes dans une base de données. +A QuerySet is, in essence, a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. Il est plus simple d'apprendre avec un exemple. Et si nous nous intéressions à celui-ci ? @@ -12,21 +12,28 @@ Il est plus simple d'apprendre avec un exemple. Et si nous nous intéressions à Ouvrez la console de votre ordinateur (et non celle de PythonAnywhere) et tapez la commande suivante : - (myvenv) ~/djangogirls$ python manage.py shell +{% filename %}command-line{% endfilename %} + (myvenv) ~/djangogirls$ python manage.py shell + Ceci devrait maintenant s'afficher dans votre console : - (InteractiveConsole) - >>> +{% filename %}command-line{% endfilename %} +```python +(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. +You're now in Django's interactive console. It's just like the Python prompt, but with some additional Django magic. :) You can use all the Python commands here too, of course. ### Lister tous les objets Essayons tout d'abord d'afficher tous nos posts. Vous pouvez le faire à l'aide de cette commande : +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.all() Traceback (most recent call last): @@ -34,59 +41,75 @@ Traceback (most recent call last): NameError: name 'Post' is not defined ``` -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" ! +Oops! An error showed up. It tells us that there is no Post. It's correct – we forgot to import it first! + +{% filename %}command-line{% endfilename %} ```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 : +We import the model `Post` from `blog.models`. Let's try displaying all posts again: + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.all() , ]> ``` -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 ? +This is a list of the posts we created earlier! We created these posts using the Django admin interface. But now we want to create new posts using Python, so how do we do that? ### Créer des objets Voici comment créer un nouveau objet Post dans la base de données : +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.create(author=me, title='Sample title', text='Test') ``` -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 ? +But we have one missing ingredient here: `me`. We need to pass an instance of `User` model as an author. How do we do that? Tout d'abord, il nous faut importer le modèle User : +{% filename %}command-line{% endfilename %} + ```python >>> from django.contrib.auth.models import User ``` Avons-nous des utilisateurs dans notre base de données ? Voyons voir : +{% filename %}command-line{% endfilename %} + ```python >>> User.objects.all() ]> ``` -C'est le superutilisateur que nous avions créé tout à l'heure ! Essayons maintenant d'obtenir une instance de l'utilisateur : +This is the superuser we created earlier! Let's get an instance of the user now: + +{% filename %}command-line{% endfilename %} ```python -me = User.objects.get(username='ola') +>>> 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. +As you can see, we now `get` a `User` with a `username` that equals 'ola'. Neat! Of course, you have to adjust this line to use your own username. Nous allons enfin pouvoir créer notre post : +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.create(author=me, title='Sample title', text='Test') ``` -Youpi ! Et si on vérifiait quand même si ça a marché ? +Et voilà ! Vous aimeriez voir ci ça a vraiment marché ? + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.all() @@ -97,46 +120,59 @@ Et voilà : un post de plus dans la liste ! ### Ajouter plus de posts -Amusez-vous à ajouter d'autres posts pour vous entrainer un peu. Essayez d'ajouter 2-3 posts en plus puis passez à la partie suivante. +You can now have a little fun and add more posts to see how it works. Add two or three more and then go ahead to the next part. ### Filtrer les objets -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: +A big part of QuerySets is the ability to filter them. Let's say we want to find all posts that user ola authored. Pour cela, nous allons utiliser `filter` à la place de `all` dans `Post.objects.all()`. In parentheses we state what condition(s) a blog post needs to meet to end up in our queryset. In our case, the condition is that `author` should be equal to `me`. The way to write it in Django is `author=me`. Maintenant, votre bout de code doit ressembler à ceci: + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(author=me) [, , , ] ``` -Et si nous voulions chercher les posts qui contiennent uniquement le mot "titre" dans le champs `title`? +Or maybe we want to see all the posts that contain the word 'title' in the `title` field? + +{% filename %}command-line{% endfilename %} ```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". +> **Note** Il y a deux tirets bas (`_`) entre `title` et `contains`. Django's ORM uses this rule to separate field names ("title") and operations or filters ("contains"). If you use only one underscore, you'll get an error like "FieldError: Cannot resolve keyword title_contains". + +You can also get a list of all published posts. We do this by filtering all the posts that have `published_date` set in the past: -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é : +{% filename %}command-line{% endfilename %} ```python >>> from django.utils import timezone >>> Post.objects.filter(published_date__lte=timezone.now()) +[] ``` -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 : +Unfortunately, the post we added from the Python console is not published yet. But we can change that! First get an instance of a post we want to publish: + +{% filename %}command-line{% endfilename %} ```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`: + +{% filename %}command-line{% endfilename %} ```python >>> post.publish() ``` -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` : +Now try to get list of published posts again (press the up arrow key three times and hit `enter`): + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.filter(published_date__lte=timezone.now()) @@ -145,7 +181,9 @@ Maintenant, essayez d'obtenir à nouveau la liste des posts publiés. Pour cela, ### Classer les objets -Les QuerySets permettent aussi de trier la liste des objets. Essayons de les trier par le champ `created_date` : +Les QuerySets permettent aussi de trier la liste des objets. Essayons de les trier par le champs `created_date` : + +{% filename %}command-line{% endfilename %} ```python >>> Post.objects.order_by('created_date') @@ -154,6 +192,8 @@ Les QuerySets permettent aussi de trier la liste des objets. Essayons de les tri On peut aussi inverser l'ordre de tri en ajouter `-` au début: +{% filename %}command-line{% endfilename %} + ```python >>> Post.objects.order_by('-created_date') [, , , ] @@ -163,15 +203,16 @@ On peut aussi inverser l'ordre de tri en ajouter `-` au début: Vous pouvez aussi combiner les QuerySets and les **chainant** les unes aux autres : -```python ->>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') -``` + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + C'est un outil très puissant qui va vous permettre d'écrire des requêtes complexes. Génial ! Vous êtes maintenant prête à passer à l'étape suivante ! Pour fermer le shell, tapez ceci: +{% filename %}command-line{% endfilename %} + ```python >>> exit() $ -``` +``` \ No newline at end of file diff --git a/fr/django_start_project/README.md b/fr/django_start_project/README.md index 16f3ce3a092..c1086d0e2ae 100755 --- a/fr/django_start_project/README.md +++ b/fr/django_start_project/README.md @@ -1,32 +1,46 @@ # Votre premier projet Django ! -> 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. +> Une partie de ce chapitre s’inspire du tutoriel des Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Parts of this chapter are based on the [django-marcador tutorial](http://django-marcador.keimlink.de/) licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. 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 ! +We're going to create a small blog! 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 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. +Il y 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. + +> N'oubliez pas de tout exécuter dans votre virtualenv. If you don't see a prefix `(myvenv)` in your console, you need to activate your virtualenv. Nous vous avons expliqué comment faire ça dans le chapitre **Installation de Django**, dans la partie **Travailler avec virtualenv**. Typing `myvenv\Scripts\activate` on Windows or `source myvenv/bin/activate` on Mac OS X or Linux will do this for you. -> 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. + -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** : +In your Mac OS X or Linux console, you should run the following command. **Don't forget to add the period (or dot) `.` at the end!** + +{% filename %}command-line{% endfilename %} (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin`. The `(myvenv) ~/djangogirls$` part shown here is just example of the prompt that will be inviting your input on your command line. + -Pour les utilisatrices de Windows, tapez la commande suivante. **N'oubliez pas le point `.` à la fin** : + - (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . +On Windows you should run the following command. **(Don't forget to add the period (or dot) `.` at the end)**: +{% filename %}command-line{% endfilename %} -> 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. + (myvenv) C:\Users\Name\djangogirls> django-admin.exe startproject mysite . + + +> The period `.` is crucial because it tells the script to install Django in your current directory (for which the period `.` is a short-hand reference). +> +> **Note** When typing the command above, remember that you only type the part which starts by `django-admin.exe`. The `(myvenv) C:\Users\Name\djangogirls>` part shown here is just example of the prompt that will be inviting your input on your command line. + + `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: @@ -37,9 +51,11 @@ Pour les utilisatrices de Windows, tapez la commande suivante. **N'oubliez pas l urls.py wsgi.py __init__.py + +> **Note**: in your directory structure, you will also see your `venv` directory that we created before. -`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. +`manage.py` is a script that helps with management of the site. With it we will be able (amongst other things) to start a web server on our computer without installing anything else. Le fichier `settings.py` contient la configuration de votre site web. @@ -51,37 +67,57 @@ Ignorons les autres fichiers pour l'instant, nous n'allons pas avoir besoin d'y Apportons quelques changements à `mysite/settings.py`. Ouvrez le fichier avec l'éditeur de code que vous avez installé tout à l'heure. -Ç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`) +**Note**: Keep in mind that `settings.py` is a regular file, like any other. You can open it from inside the code editor, using the "file -> open" menu actions. This should get you the usual window in which you can navigate to your `settings.py` file and select it. Alternatively, you can open the file by navigating to the djangogirls folder on your desktop and right-clicking on it. Then, select your code editor from the list. Selecting the editor is important as you might have other programs installed that can open the file but will not let you edit it. + +Ça serait sympa d'avoir l'heure correcte sur notre site Web. Go to [Wikipedia's list of time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) and copy your relevant time zone (TZ) (e.g. `Europe/Berlin`). + +In `settings.py`, find the line that contains `TIME_ZONE` and modify it to choose your own timezone. For example: + +{% filename %}mysite/settings.py{% endfilename %} + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +A language code consist of the language, e.g. `en` for english or `de` for german, and the country code, e.g. `de` for germany or `ch` for switzerland. You will want to add this if you want the default buttons and notifications from Django to be in your language. So you would have "Cancel" button translated into the language you defined here. [Django comes with a lot of prepared translations](https://docs.djangoproject.com/en/1.11/ref/settings/#language-code). - [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +Change the language code by changing the following line: -Dans settings.py, recherchez la ligne qui contient le `TIME_ZONE` et modifiez-la pour choisir votre propre fuseau horaire : +{% filename %}mysite/settings.py{% endfilename %} ```python -TIME_ZONE = 'Europe/Paris' +LANGUAGE_CODE = 'de-ch' ``` -En remplaçant "Europe/Paris" par la valeur appropriée +We'll also need to add a path for static files. (We'll find out all about static files and CSS later in the tutorial.) Go down to the *end* of the file, and just underneath the `STATIC_URL` entry, add a new one called `STATIC_ROOT`: -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` : +{% filename %}mysite/settings.py{% endfilename %} ```python STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') ``` -Quand `DEBUG` est à `True` et `ALLOWED_HOSTS` est vide, les ordinateurs qui sont autorisés à servir notre site web sont ceux de la liste `['localhost', '127.0.0.1', '[::1]']`. Plus loin dans ce tutorial, nous allons déployer le site web sur PythonAnywhere, donc nous allons anticiper un peu et ajouter le nom de domaine correspondant : +When `DEBUG` is `True` and `ALLOWED_HOSTS` is empty, the host is validated against `['localhost', '127.0.0.1', '[::1]']`. This won't match our hostname on PythonAnywhere once we deploy our application so we will change the following setting: + +{% filename %}mysite/settings.py{% endfilename %} ```python -ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] +ALLOWED_HOSTS = ['127.0.0.1', '.pythonanywhere.com'] ``` -## Configuration de la base de données +> **Note**: If you're using a Chromebook, add this line at the bottom of your settings.py file: `MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'` +> +> Also add `.c9users.io` to the `ALLOWED_HOSTS` if you are using cloud9 + +## Set up a database -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 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 va utiliser celui par défaut : `sqlite3`. Il est déjà configuré dans cette partie de votre fichier `mysite/settings.py`: +{% filename %}mysite/settings.py{% endfilename %} + ```python DATABASES = { 'default': { @@ -93,51 +129,74 @@ DATABASES = { 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: +{% filename %}command-line{% endfilename %} + (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... + Apply all migrations: auth, admin, contenttypes, sessions Running migrations: Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... 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 auth.0007_alter_validators_add_error_messages... OK Applying sessions.0001_initial... OK - + Et voilà ! Il ne reste plus qu'à lancer le serveur et voir si notre site web fonctionne ! +## Starting the web server + 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`: +{% filename %}command-line{% endfilename %} + (myvenv) ~/djangogirls$ python manage.py runserver + +If you are on a Chromebook, use this command instead: + +{% filename %}Cloud 9{% endfilename %} + + (myvenv) ~/djangogirls$ python manage.py runserver 0.0.0.0:8080 + Si vous utilisez Windows et que vous obtenez l'erreur `UnicodeDecodeError`, tapez plutôt cette commande : +{% filename %}command-line{% endfilename %} + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + +Now all you need to do is check that your website is running. Open your browser (Firefox, Chrome, Safari, Internet Explorer or whatever you use) and enter this address: -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 : +{% filename %}browser{% endfilename %} http://127.0.0.1:8000/ + +If you're using a Chromebook, you'll always visit your test server by accessing: -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. +{% filename %}browser{% endfilename %} + + https://django-girls-.c9users.io + 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é !][3] +![Ça a marché!](images/it_worked2.png) + +While the web server is running, you won't see a new command-line prompt to enter additional commands. The terminal will accept new text but will not execute new commands. This is because the web server continuously runs in order to listen for incoming requests. + +> We reviewed how web servers work in the **How the Internet works** chapter. - [3]: images/it_worked2.png +To type additional commands while the web server is running, open a new terminal window and activate your virtualenv. To stop the web server, switch back to the window in which it's running and press CTRL+C - Control and C keys together (on Windows, you might have to press Ctrl+Break). -Prête pour la suite ? Il est temps de créer du contenu! +Prête pour la suite ? Il est temps de créer du contenu! \ No newline at end of file diff --git a/fr/django_templates/README.md b/fr/django_templates/README.md index f9605fb119b..29bb5b0dcdd 100755 --- a/fr/django_templates/README.md +++ b/fr/django_templates/README.md @@ -4,9 +4,9 @@ Il est temps d'afficher des données ! Pour nous aider, Django fournit des balis ## Qu'est-ce que c'est que des balises de template ? -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. +You see, in HTML, you can't really write Python code, because browsers don't understand it. They know only HTML. We know that HTML is rather static, while Python is much more dynamic. -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 ? +**Django template tags** allow us to transfer Python-like things into HTML, so you can build dynamic websites faster. Cool! ## Template d'affichage de la liste des posts @@ -14,24 +14,28 @@ Dans le chapitre précédent, nous avons donné à notre template une liste de p 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 : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```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 `
` jusqu'au troisième `
` avec la ligne `{{ posts }}`. Sauvegardez votre fichier et rafraichissez votre page pour voir le résultat : -![Figure 13.1][1] - - [1]: images/step1.png +![Figure 13.1](images/step1.png) Comme vous pouvez le voir, tout ce que nous avons, c'est ceci : -```python +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + +```html , ]> ``` 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 : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html {% for post in posts %} {{ post }} @@ -40,11 +44,11 @@ Cela signifie que Django l'interprète comme une liste d'objets. Essayez de vous Essayez ceci dans votre template. -![Figure 13.2][2] +![Figure 13.2](images/step2.png) - [2]: images/step2.png +Ça marche ! But we want the posts to be displayed like the static posts we created earlier in the **Introduction to HTML** chapter. 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 : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html
@@ -53,7 +57,7 @@ Essayez ceci dans votre template. {% for post in posts %}
-

publié: {{ post.published_date }}

+

published: {{ post.published_date }}

{{ post.title }}

{{ post.text|linebreaksbr }}

@@ -62,18 +66,18 @@ Essayez ceci dans votre template. {% 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] +![Figure 13.3](images/step3.png) - [3]: images/step3.png +Have you noticed that we used a slightly different notation this time (`{{ post.title }}` or `{{ post.text }})`? Nous accédons aux données associées à chaque champ défini dans notre modèle `Post`. Also, the `|linebreaksbr` is piping the posts' text through a filter to convert line-breaks into paragraphs. -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. +## Une dernière chose -## Encore une chose ! +It'd be good to see if your website will still be working on the public Internet, right? Let's try deploying to PythonAnywhere again. Here's a recap of the steps… -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... +* En premier lieu, envoyez votre code sur GitHub (push) + +{% filename %}command-line{% endfilename %} -* En premier lieu, envoyez votre code sur GitHub (push) -``` $ git status [...] $ git add --all . @@ -82,25 +86,21 @@ Maintenant, ça serait bien de voir si votre site Web fonctionne toujours sur In $ git commit -m "Modified templates to display posts from database." [...] $ git push -``` + -* Ensuite, reconnectez-vous à [PythonAnywhere][4] et allez sur la "**Bash console**" (ou démarrez-en une nouvelle), et lancez les commandes suivantes : +* Ensuite, reconnectez-vous à [PythonAnywhere](https://www.pythonanywhere.com/consoles/) et allez sur la "**Bash console**" (ou démarrer-en une nouvelle), et lancez les commandes suivantes : + +{% filename %}PythonAnywhere command-line{% endfilename %} - [4]: https://www.pythonanywhere.com/consoles/ -``` $ cd my-first-blog $ git pull [...] -``` - -* 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. +* Finalement, allez sur l'[onglet Web](https://www.pythonanywhere.com/web_app_setup/) et cliquez sur **Reload** sur votre application web. Votre site mis-à-jour devrait être en ligne ! If the blog posts on your PythonAnywhere site don't match the posts appearing on the blog hosted on your local server, that's OK. The databases on your local computer and Python Anywhere don't sync with the rest of your files. -Ç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. :) +Félicitations! Now go ahead and try adding a new post in your Django admin (remember to add published_date!) Make sure you are in the Django admin for your pythonanywhere site, https://yourname.pythonanywhere.com/admin. Then refresh your page to see if the post appears there. -![Figure 13.4][6] +Works like a charm? We're proud! Step away from your computer for a bit – you have earned a break. :) - [6]: images/donut.png +![Figure 13.4](images/donut.png) \ No newline at end of file diff --git a/fr/django_urls/README.md b/fr/django_urls/README.md index 93afdcca466..d2079a4bee3 100755 --- a/fr/django_urls/README.md +++ b/fr/django_urls/README.md @@ -1,21 +1,21 @@ -# Les urls Django +# Django URLs -Nous sommes sur le point de construire notre première page web : la page d'accueil de notre blog ! Avant de passer à la partie code, apprenons-en un peu plus sur les urls Django. +We're about to build our first webpage: a homepage for your blog! But first, let's learn a little bit about Django URLs. ## Qu'est-ce qu'une URL ? -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) : +Une URL est simplement une adresse web. You can see a URL every time you visit a website – it is visible in your browser's address bar. (Yes! `127.0.0.1:8000` est aussi une URL ! And `https://djangogirls.org` is also a URL.) -![Url][1] +![Url](images/url.png) - [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 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. +Chaque page internet a besoin de sa propre URL. This way your application knows what it should show to a user who opens that URL. Dans Django, nous utilisons un outil appelé `URLconf` (configuration des URLs) : URLconf is a set of patterns that Django will try to match with the requested URL to find the correct view. ## Comment les URLs fonctionnent-elles dans Django ? Ouvrons le fichier `mysite/urls.py` dans notre éditeur de code et regardons à quoi il ressemble : +{% filename %}mysite/urls.py{% endfilename %} + ```python """mysite URL Configuration @@ -29,55 +29,58 @@ urlpatterns = [ ] ``` -Comme vous pouvez le voir, Django nous a déjà préparé une partie du travail. +As you can see, Django has already put something here for us. + +Lines between triple quotes (`'''` or `"""`) are called docstrings – you can write them at the top of a file, class or method to describe what it does. They won't be run by Python. -Les lignes encadrées par trois guillemets (`"""` ou `'''`) sont appelées docstrings ; nous pouvons les ajouter au début de nos fichiers, de nos classes ou de nos méthodes pour décrire ce qu'elles font. Ces lignes ne seront donc pas exécutées par Python. +The admin URL, which you visited in previous chapter, is already here: -Comme vous pouvez le voir, l'adresse de l'interface d'administration est déjà en place : +{% filename %}mysite/urls.py{% endfilename %} ```python url(r'^admin/', 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. +This line means that for every URL that starts with `admin/`, Django will find a corresponding *view*. In this case we're including a lot of admin URLs so it isn't all packed into this small file – it's more readable and cleaner. ## 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` ("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. +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 chaine 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 : +If you still wish to understand how we created the patterns, here is an example of the process – we will only need a limited subset of the rules to express the pattern we are looking for, namely: - ^ -> 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 +* `^` for the beginning of the text +* `$` for the end of the text +* `\d` for a digit +* `+` to indicate that the previous item should be repeated at least once +* `()` to capture part of the pattern +Anything else in the URL definition will be taken literally. -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. +Now imagine you have a website with the address like `http://www.mysite.com/post/12345/`, where `12345` is the number of your post. -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. With regular expressions, we can create a pattern that will match the URL and extract the number for us: `^post/(\d+)/$`. Let's break this down piece by piece to see what we are doing here: -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/** is telling Django to take anything that has `post/` at the beginning of the url (right after `^`) +* **(\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 chaines de caractères se terminant par `/` correspondrons au pattern -* **^ 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 +## Your first Django URL! -## Votre première URL Django ! +Time to create our first URL! We want 'http://127.0.0.1:8000/' to be the home page of our blog and to display a list of 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 : ajoutez une ligne qui va nous permettre d'importer `blog.urls` dans notre URL principale (`''`). Notez que nous utilisons ici la fonction `include` et qu'il est donc nécessaire de l'ajouter à l'import de la première ligne de notre fichier. +We also want to keep the `mysite/urls.py` file clean, so we will import URLs from our `blog` application to the main `mysite/urls.py` file. +Go ahead, add a line that will import `blog.urls`. Note that we are using the `include` function here so you will need to add that import. Votre fichier `mysite/urls.py` devrait maintenant ressembler à ceci: +{% filename %}mysite/urls.py{% endfilename %} + ```python -from django.conf.urls import include, url +from django.conf.urls import include +from django.conf.urls import url from django.contrib import admin urlpatterns = [ @@ -88,39 +91,39 @@ urlpatterns = [ 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. -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. +Writing regular expressions in Python is always done with `r` in front of the string. Cela permet d'indiquer à Python que ce qui va suivre inclus 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 nouveau fichier vide `blog/urls.py`. OK ! Ajoutez maintenant ces deux premières lignes : +Create a new empty file named `urls.py` in the `blog` directory. All right! Add these first two lines: + +{% filename %}blog/urls.py{% endfilename %} ```python from django.conf.urls import url from . import views ``` -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 +Here we're importing Django's function `url` and all of our `views` from the `blog` application. (We don't have any yet, but we will get to that in a minute!) Après ça, nous pouvons ajouter notre premier pattern d'URL: +{% filename %}blog/urls.py{% endfilename %} + ```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 `^$`. 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/". - -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 tout fonctionne toujours ? Ouvrez votre navigateur à l'adresse http://127.0.0.1:8000/ pour vérifier. +As you can see, we're now assigning a `view` called `post_list` to the `^$` URL. This regular expression will match `^` (a beginning) followed by `$` (an end) – so only an empty string will match. Ç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/". -![Erreur][2] +The last part, `name='post_list'`, is the name of the URL that will be used to identify the view. Ce nom peut être le même que celui de la vue ou quelque chose de complètement différent. We will be using the named URLs later in the project, so it is important to name each URL in the app. We should also try to keep the names of URLs unique and easy to remember. - [2]: images/error1.png +If you try to visit http://127.0.0.1:8000/ now, then you'll find some sort of 'web page not available' message. This is because the server (remember typing `runserver`?) is no longer running. Take a look at your server console window to find out why. -"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 : +![Erreur](images/error1.png) -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 :). +Your console is showing an error, but don't worry – it's actually pretty useful: It's telling you that there is **no attribute 'post_list'**. That's the name of the *view* that Django is trying to find and use, but we haven't created it yet. At this stage your `/admin/` will also not work. No worries – we will get there. -> 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.11/topics/http/urls/ +> 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.11/topics/http/urls/ \ No newline at end of file diff --git a/fr/django_views/README.md b/fr/django_views/README.md index 429c93c1b3a..59c6827d442 100755 --- a/fr/django_views/README.md +++ b/fr/django_views/README.md @@ -1,8 +1,8 @@ -# Créons nos vues Django! +# Django views – time to create! -Il est enfin temps de se débarrasser du bug que nous avons créé dans le chapitre précédent :) +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`. 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**. +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. Views are just Python functions that are a little bit more complicated than the ones we wrote in the **Introduction to Python** chapter. Les vues sont placées dans le fichier `views.py`. Nous allons créer nos *vues* dans le fichier `blog/views.py`. @@ -10,33 +10,35 @@ 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 : +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render # Create your views here. ``` -Il n'y pas encore grand chose dans ce fichier. +Not too much stuff here yet. + +Remember that lines starting with `#` are comments – this means that those lines won't be run by Python. -Les lignes qui commencent par `#` permettent de commenter notre code : ces lignes ne seront donc pas exécutées par Python. Pratique, non ? +Let's create a *view* as the comment suggests. Add the following minimal view below it: -La vue la plus simple que l'on peut créer ressemble à ceci : +{% filename %}blog/views.py{% endfilename %} ```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é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`. +As you can see, we created a function (`def`) called `post_list` that takes `request` and `return` a function `render` that will render (put together) our 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. +Save the file, go to http://127.0.0.1:8000/ and see what we've got. Une autre erreur ! Voyons ce qu'elle nous dit : -![Erreur][1] - - [1]: images/error.png +![Erreur](images/error.png) -Celle-là est plutôt simple : *TemplateDoesNotExist*. Corrigeons ça en créant un template dans la section suivante ! +This shows that the server is running again, at least, but it still doesn't look right, does it? Don't worry, it's just an error page, nothing to be scared of! Just like the error messages in the console, these are actually pretty useful. You can read that the *TemplateDoesNotExist*. Let's fix this bug and create a template in the next chapter! -> Pour en apprendre un peu plus sur les vues dans Django, consultez la documentation officielle : https://docs.djangoproject.com/fr/1.11/topics/http/views/ +> Pour en apprendre un peu plus sur les vues dans Django, consultez la documentation officielle : https://docs.djangoproject.com/en/1.11/topics/http/views/ \ No newline at end of file diff --git a/fr/dynamic_data_in_templates/README.md b/fr/dynamic_data_in_templates/README.md index 137968bac8d..26f14635293 100755 --- a/fr/dynamic_data_in_templates/README.md +++ b/fr/dynamic_data_in_templates/README.md @@ -1,13 +1,15 @@ # 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. +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 ? Because that is what we want to do – take some content (models saved in the database) and display it nicely in our template, right? -C'est à ça que servent les *vues* : connecter les modèles et les templates. Dans notre *vue* `post_list`, nous allons avoir besoin de prendre les modèles dont nous avons besoin et de les passer au template. Concrètement, c'est dans la *vue* que nous allons décider ce qui va s'afficher (modèle) dans un template. +C'est à ça que servent les *vues* : connecter les modèles et les templates. In our `post_list` *view* we will need to take the models we want to display and pass them to the template. In a *view* we decide what (model) will be displayed in a template. -Ok, et sinon, on fait comment ? +OK, so how will we achieve this? Nous allons avoir besoin d'ouvrir le fichier `blog/views.py`. Pour l'instant, la *vue* `post_list` ressemble à ceci : +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render @@ -15,28 +17,34 @@ def post_list(request): return render(request, 'blog/post_list.html', {}) ``` -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 : +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. Now is the moment when we have to include the model we have written in `models.py`. We will add the line `from .models import Post` like this: + +{% filename %}blog/views.py{% endfilename %} ```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`). +The dot before `models` means *current directory* or *current application*. Both `views.py` and `models.py` are in the same directory. This means we can use `.` and the name of the file (without `.py`). Ensuite, nous importons le modèle (`Post`). -Ok, et après ? Afin de pouvoir aller chercher les véritables posts de blog de notre modèle `Post`, nous avons besoin de quelque chose qui s'appelle un `QuerySet`. +But what's next? To take actual blog posts from the `Post` model we need something called `QuerySet`. ## QuerySet -Normalement, ce mot doit vous évoquer quelque chose. Nous en avons un peu parlé dans la section [Django ORM (QuerySets)][1]. +You should already be familiar with how QuerySets work. We talked about them in [Django ORM (QuerySets) chapter](../django_orm/README.md). + +So now we want published blog posts sorted by `published_date`, right? We already did that in QuerySets chapter! -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 ! +{% filename %}blog/views.py{% endfilename %} ```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)` : +Now we put this piece of code inside the `blog/views.py` file by adding it to the function `def post_list(request)`, but don't forget to first add `from django.utils import timezone`: + +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render @@ -48,16 +56,16 @@ def post_list(request): 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. +The last missing part is passing the `posts` QuerySet to the template context. Don't worry – we will cover how to display it in a later chapter. -Notez aussi que notre code utilise la fonction `timezone.now()` que nous allons aussi devoir importer de `timezone`. - -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. +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. -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 `''`. +In the `render` function we have one parameter `request` (everything we receive from the user via the Internet) and another giving the template file (`'blog/post_list.html'`). The last parameter, `{}`, is a place in which we can add some things for the template to use. Nous avons par exemple de lui donner des noms : nous allons rester sur `'posts'` pour le moment). :) Ça va ressembler à ça : `{'posts': posts}`. Please note that the part before `:` is a string; you need to wrap it with quotes: `''`. Au final, notre fichier `blog/views.py` doit ressembler à ceci maintenant : +{% filename %}blog/views.py{% endfilename %} + ```python from django.shortcuts import render from django.utils import timezone @@ -70,6 +78,4 @@ def post_list(request): 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/fr/1.11/ref/models/querysets/ - - [1]: ../django_orm/README.md +Want to read a little bit more about QuerySets in Django? You should look here: https://docs.djangoproject.com/en/1.11/ref/models/querysets/ \ No newline at end of file diff --git a/fr/extend_your_application/README.md b/fr/extend_your_application/README.md index 5489fff0887..4127d55b741 100755 --- a/fr/extend_your_application/README.md +++ b/fr/extend_your_application/README.md @@ -10,7 +10,7 @@ Nous avons déjà un modèle `Post`, nous n'avons donc pas besoin de retourner ## Créer un lien dans un template -Nous allons tout d'abord ajouter un lien à l'intérieur du fichier `blog/templates/blog/post_list.html`. Pour le moment, ce fichier doit ressembler à ceci : +Nous allons commencer par ajouter un lien à l’intérieur du fichier `blog/templates/blog/post_list.html`. À ce stade, il devrait ressembler à ceci :{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -30,19 +30,21 @@ Nous allons tout d'abord ajouter un lien à l'intérieur du fichier `blog/templa {% 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 %} +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html

{{ post.title }}

``` {% 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*. +The `post_detail` part means that Django will be expecting a URL in `blog/urls.py` with name=post_detail -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 : +Et qu’en est-il `pk=post.pk` ? `pk` est l’abréviation de clé primaire ("primary key" en anglais), qui est une référence unique pour chaque élément enregistré dans une base de données. Comme nous n'avons pas spécifiée de clé primaire dans notre modèle `Post`, Django en crée une pour nous (par défaut, un nombre qui augmente d’un pour chaque enregistrement, c'est-à-dire 1, 2, 3 etc..) et l’ajoute comme un champ nommé `pk` à chacun de nos posts. Nous accédons à la clé primaire en écrivant `post.pk`, de la même manière, que nous pouvons accéder autres champs (`titre`, `auteur`, etc...) dans notre objet de `Post` ! -![Erreur NoReverseMatch][1] +Maintenant si on jette un coup d’œil à : http://127.0.0.1:8000/, nous rencontrons une erreur. Ceci est prévisible puisque nous n'avons pas d'URL ni de *view* pour `post_detail`. L'erreur ressemble à ceci : - [1]: images/no_reverse_match2.png +![Erreur NoReverseMatch](images/no_reverse_match2.png) ## Créer une URL vers le contenu d'un post @@ -50,7 +52,9 @@ Allons créer notre URL dans le fichier `urls.py` pour notre *vue* `post_detail` Nous aimerions que le contenu de notre premier post s'affiche à cette **URL** : http://127.0.0.1:8000/post/1/ -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 : +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. Add the line `url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'),` to the `blog/urls.py` file. Votre fichier devrait maintenant ressembler à ceci : + +{% filename %}blog/urls.py{% endfilename %} ```python from django.conf.urls import url @@ -58,62 +62,63 @@ 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/(?P\d+)/$', views.post_detail, name='post_detail'), ] ``` -`^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"! +This part `^post/(?P\d+)/$` looks scary, but no worries – we will explain it for you: -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*. +- it starts with `^` again – "the beginning". +- `post/` just means that after the beginning, the URL should contain the word **post** and a **/**. So far so good. +- `(?P\d+)` – this part is trickier. 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`. (Note that this matches the name we gave the primary key variable back in `blog/templates/blog/post_list.html`!) `\d` also tells us that it can only be a digit, not a letter (so everything between 0 and 9). `+` signifie qu'il faut, au minimum, un chiffre à cet endroit. So something like `http://127.0.0.1:8000/post//` is not valid, but `http://127.0.0.1:8000/post/1234567890/` is perfectly OK! +- `/` – then we need a **/** again. +- `$` – "the end"! -`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]+)`. - -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 ;) +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*. -![AttributeError][2] +OK, we've added a new URL pattern to `blog/urls.py`! Let's refresh the page: http://127.0.0.1:8000/ Boom! The server has stopped running again. Have a look at the console – as expected, there's yet another error! - [2]: images/attribute_error2.png +![AttributeError](images/attribute_error2.png) Est-ce que vous vous souvenez de ce que nous devons faire ensuite ? Il falloir ajouter une vue ! ## Ajouter une vue pour le contenu du post -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 ! +This time our *view* is given an extra parameter, `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 incorrect et va générer une erreur ! -Maintenant, nous n'aimerions obtenir qu'un seul blog post. Pour cela, nous allons utiliser des QuerySets qui ressemblent à ceux-ci: +Now, we want to get one and only one blog post. To do this, we can use querysets, like this: + +{% filename %}blog/views.py{% endfilename %} ```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ède cette `primary key (clef primaire)` (`pk`), nous allons nous retrouver avec une super erreur bien cracra! +But this code has a problem. If there is no `Post` with the given `primary key` (`pk`) we will have a super ugly error! -![Erreur DoesNotExist][3] +![Erreur DoesNotExist](images/does_not_exist2.png) - [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`. In case there is no `Post` with the given `pk`, it will display much nicer page, the `Page Not Found 404` page. -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](images/404_2.png) -![Page non trouvée][4] +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 ;). - [4]: images/404_2.png +OK, time to add a *view* to our `views.py` file! -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 ;). +In `blog/urls.py` we created a URL rule named `post_detail` that refers to a view called `views.post_detail`. This means that Django will be expecting a view function called `post_detail` inside `blog/views.py`. -Ok, ajoutons notre *vue* à notre fichier `views.py`! +We should open `blog/views.py` and add the following code near the other `from` lines: -Ouvrons le fichier `blog/views.py` et ajoutons le code suivant: +{% filename %}blog/views.py{% endfilename %} ```python from django.shortcuts import render, get_object_or_404 ``` -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: +And at the end of the file we will add our *view*: + +{% filename %}blog/views.py{% endfilename %} ```python def post_detail(request, pk): @@ -123,23 +128,21 @@ def post_detail(request, pk): Hop, réactualisons la page http://127.0.0.1:8000/ -![Vue post_list][5] +![Vue post_list](images/post_list2.png) - [5]: images/post_list2.png +C'est bon, ç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] - - [6]: images/template_does_not_exist2.png +![Erreur TemplateDoesNotExist](images/template_does_not_exist2.png) 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 +## Create a template for the post details Nous allons créer un fichier `post_detail.html` dans le dossier `blog/templates/blog`. -Ça ressemblera à ça : +Le résultat devrait ressembler à ça : + +{% filename %}blog/templates/blog/post_detail.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -159,13 +162,11 @@ Nous allons créer un fichier `post_detail.html` dans le dossier `blog/templates 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 à Python**. Dans ce scénario, nous aimerions vérifier si la date de publication d'un post (`published_date`) n'est pas vide.{% 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, vous pouvez maintenant rafraîchir votre page et voir si la page `Page not found` a enfin disparu. -![Page détaillée d'un post][7] - - [7]: images/post_detail2.png +![Page détaillée d'un post](images/post_detail2.png) Yay ! Ça marche! @@ -173,27 +174,24 @@ Yay ! Ça marche! 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 :) +{% filename %}command-line{% endfilename %} + $ 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](https://www.pythonanywhere.com/consoles/): -* Puis, dans la console bash de [PythonAnywhere][8]: - - [8]: 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 [...] + +Enfin, cliquez sur l'onglet [Web](https://www.pythonanywhere.com/web_app_setup/) et cliquez sur **Reload**. -* 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 :) +Normalement, ça devrait suffire ! Encore bravo :) \ No newline at end of file diff --git a/fr/how_the_internet_works/README.md b/fr/how_the_internet_works/README.md index 4445c403ad0..215698ade78 100644 --- a/fr/how_the_internet_works/README.md +++ b/fr/how_the_internet_works/README.md @@ -1,52 +1,47 @@ # 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/). +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. +> +> This chapter is inspired by the talk "How the Internet works" by Jessica McKellar (http://web.mit.edu/jesstess/www/). -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` ? +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`? 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é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. +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. That's why they're called *servers* – because they *serve* you data. -Bon, d'accord. Mais vous avez envie de savoir à quoi Internet ressemble, n'est-ce-pas ? +OK, but you want to know how the Internet looks, right? -On va a fait un dessin ! Internet ressemble à ça : +Nous vous avons fait un dessin ! Voilà à quoi ça ressemble : -![Figure 1.1][1] +![Figure 1.1](images/internet_1.png) - [1]: images/internet_1.png +C'est le bazar, non ? In fact it is a network of connected machines (the above-mentioned *servers*). Des centaines de milliers de machines ! Des millions de kilomètres de câbles, partout dans le monde ! Vous pouvez aller voir une carte des câbles sous-marins (http://submarinecablemap.com/) pour voir à quel point le réseau est compliqué. Voici une capture d'écran du site : -C'est le bazar, non ? En fait, c'est un réseau de machines connectées entre elles (les *serveurs* dont on parlait plus tôt). Des centaines de milliers de machines ! Des millions de kilomètres de câbles, partout dans le monde ! Vous pouvez aller voir une carte des câbles sous-marins (http://submarinecablemap.com/) pour voir à quel point le réseau est compliqué. Voici une capture d'écran du site : +![Figure 1.2](images/internet_3.png) -![Figure 1.2][2] - - [2]: images/internet_3.png - -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. +Fascinant, non ? Cependant, il n'est évidemment pas possible de tirer un câble entre chaque machine connectée à 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. Ça ressemble ça : -![Figure 1.3][3] - - [3]: images/internet_2.png +![Figure 1.3](images/internet_2.png) -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 ?" +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!" 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] +![Figure 1.4](images/internet_4.png) - [4]: images/internet_4.png +That's how it works - 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! -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. 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. -À 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. +When you send a letter, it needs to have certain features to be delivered correctly: an address, a stamp, etc. 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). -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/0> (dans une lettre), il envoie votre site Web (dans une autre lettre).

-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 :). +Since this is a Django tutorial, you might ask what Django does. 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 parlé, il est temps de commencer à créer des trucs ! \ No newline at end of file +Enough talk – time to create! \ No newline at end of file diff --git a/fr/html/README.md b/fr/html/README.md index 9b06a7f8817..9862f9c073e 100755 --- a/fr/html/README.md +++ b/fr/html/README.md @@ -2,13 +2,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. +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. -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**). +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**). ## 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 is a code that is interpreted by your web browser – such as Chrome, Firefox or Safari – to display a web page for the user. 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. @@ -21,24 +21,24 @@ Les templates sont sauvegardés dans le dossier `blog/templates/blog`. Tout d'ab 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.) -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 `blog/templates/blog`. +Et maintenant, créez un fichier `post_list.html` (laisser le vide pour le moment) dans le dossier `templates/blog/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 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] +> 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 keys together) and start it again by running a `python manage.py runserver` command. - [1]: images/step1.png +![Figure 11.1](images/step1.png) Et voilà, il n'y a plus d'erreurs ! Bravo :) Cependant, notre site ne peut rien faire d'autre pour le moment qu'afficher une page blanche. La faute à notre template que nous avons laissé vide. Allons corriger ça. Ajoutez ce qui suit à votre fichier template : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} + ```html

Hi there!

@@ -46,33 +46,33 @@ Ajoutez ce qui suit à votre fichier template : ``` -Alors, à quoi ressemble notre site web maintenant ? Allons le découvrir : 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][2] - - [2]: images/step3.png +![Figure 11.2](images/step3.png) Ça marche ! Bon boulot :) -* La balise la plus élémentaire, ``, figure toujours au début de n'importe quelle page web tandis que `` est toujours située à la fin. Comme vous pouvez le constater, l'intégralité du contenu de notre page web est située entre la balise de départ, ``, et la balise fermante, `` -* `

` est la balise pour les éléments de type paragraphe. `

` permet de fermer chaque paragraphe. +* The most basic tag, ``, is always the beginning of any web page and `` is always the end. Comme vous pouvez le constater, l'intégralité du contenu de notre page web est située entre la balise de départ, ``, et la balise fermante, `` +* `

` est la balise pour les éléments de type paragraphe. `

` permet de fermer chaque paragraphe. -## Head & body +## Head and body -Chaque page HTML est divisée en deux éléments : **head** (entête) et **body** (corps). +Chaque page HTML est divisée en deux éléments : **head** (entête) et **body** (corps. -* **head** est un élément qui contient des informations sur le document : son contenu ne s'affichera pas à l'écran. +* **head** est un élément qui contient des informations sur le document : son contenu ne s'affichera pas à l'écran. -* **body** est un élément qui contient tout le reste. Son contenu s'affichera à l'écran et constituera notre page web. +* **body** est un élément qui contient tout le reste. Son contenu s'affichera à l'écran et constituera notre page web. Nous utilisons `` pour transmettre la configuration de la page au navigateur tandis que `` l'informe sur le contenu de la page. -Par exemple, vous pouvez donner un titre à votre site en utilisant l'élément titre dans le `` : +For example, you can put a web page title element inside the ``, like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - Le Blog d'Ola + Ola's blog

Hi there!

@@ -83,9 +83,7 @@ Par exemple, vous pouvez donner un titre à votre site en utilisant l'élément Sauvegardez votre fichier et actualisez la page. -![Figure 11.3][3] - - [3]: images/step4.png +![Figure 11.3](images/step4.png) Vous avez vu comment le navigateur a compris que « Le Blog d'Ola » est le titre de votre page ? Il a interprété `Le blog d'Ola` et a placé ce texte dans la barre de titre de votre navigateur (c'est ce titre qui va être aussi utilisé lorsque vous créez un marque-page, etc.). @@ -93,23 +91,26 @@ Vous avez aussi probablement remarqué que chaque balise ouvrante possède sa *b Pensez à lorsque vous mettez des choses à l'intérieur de boîtes. Vous avez une grosse boîte, ``; à l'intérieur de celle-ci, on trouve une plus petite boîte, ``, qui contient elle-même d'autres petites boîtes, `

`. -Essayez de vous rappeler cet exemple lorsque vous utilisez les balises *fermantes* et que vous avez des éléments *imbriqués*. Si vous ne suivez pas ces règles, votre navigateur risque de ne pas être capable d'interpréter votre code correctement et risque de mal afficher votre page web. +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. ## Personnaliser votre template Et si nous en profitions pour nous amuser un peu ? Essayons de personnaliser notre template ! Voici quelques balises que vous pouvez utiliser : -* `

Titre 1

` - pour vos titres les plus importants -* `

Titre 2

` - pour les sous-titres -* `

Titre 3

` ... et ainsi de suite jusqu'à `
` -* `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 -* `
  • 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 +* `

A heading

` for your most important heading +* `

Titre 2

` - pour les sous-titres +* `

A sub-sub-heading

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

A paragraph of text

` +* `texte` permet de mettre l'accent sur une partie du texte +* `texte` permet de mettre encore plus l'accent sur une partie de texte +* `
` goes to another line (you can't put anything inside br and there's no closing tag) +* `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 + +Here's an example of a full template, copy and paste it into `blog/templates/blog/post_list.html`: -Voici un exemple de template utilisant plusieurs balises : +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html @@ -118,7 +119,7 @@ Voici un exemple de template utilisant plusieurs balises :
@@ -138,18 +139,16 @@ Voici un exemple de template utilisant plusieurs balises : Nous avons créé trois sections à l'aide de `div`. -* 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. +* The first `div` element contains the title of our blog – it's a heading and a link +* 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. Ce qui nous donne : -![Figure 11.4][4] +![Figure 11.4](images/step6.png) - [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 ! 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. Penchons-nous là dessus. +What we really want to do is display real posts added in our Django admin – and that's where we're going next. ## Une dernière chose : déployer ! @@ -159,51 +158,56 @@ Ne serait-il pas génial de pouvoir voir tout ces changements en ligne ? Hop, d 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 +{% filename %}command-line{% endfilename %} + $ git status + 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 : +{% filename %}command-line{% endfilename %} + $ git add --all . + +> **Note** `--all` means that `git` will also recognize if you've deleted files (by default, it only recognizes new/modified files). 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) : +{% filename %}command-line{% endfilename %} $ 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" +{% filename %}command-line{% endfilename %} + $ 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 nous avons fait cela, nous pouvons mettre en ligne (pusher) nos modifications sur GitHub : +Once we've done that, we upload (push) our changes up to GitHub: - git push +{% filename %}command-line{% endfilename %} + $ 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 : +* Allez sur la page des [consoles de PythonAnywhere](https://www.pythonanywhere.com/consoles/). Retournez dans votre **console Bash** ou ouvrez-en une nouvelle puis tapez la commande suivante : - [5]: 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 [...] - + 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**. - - [6]: https://www.pythonanywhere.com/web_app_setup/ +* Pour finir, n'oubliez pas de recharger votre application web : onglet [web](https://www.pythonanywhere.com/web_app_setup/) puis cliquez sur le bouton **Reload**. -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 :) +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'aider à votre coach. :) \ No newline at end of file diff --git a/fr/install_git.md b/fr/install_git.md new file mode 100644 index 00000000000..e7d88e0ffb4 --- /dev/null +++ b/fr/install_git.md @@ -0,0 +1,52 @@ +Git is a "version control system" used by a lot of programmers. This software can track changes to files over time so that you can recall specific versions later. A bit like the "track changes" feature in Microsoft Word, but much more powerful. + +## Installing Git + + + +You can download Git from [git-scm.com](https://git-scm.com/). You can hit "next" on all steps except for one; in the fifth step entitled "Adjusting your PATH environment", choose "Use Git and optional Unix tools from the Windows Command Prompt" (the bottom option). Other than that, the defaults are fine. Checkout Windows-style, commit Unix-style line endings is good. + +Do not forget to restart the command prompt or powershell after the installation finished successfully. + + + +Download Git from [git-scm.com](https://git-scm.com/) and just follow the instructions. + +> **Note** If you are running OS X 10.6, 10.7, or 10.8, you will need to install the version of git from here: [Git installer for OS X Snow Leopard](https://sourceforge.net/projects/git-osx-installer/files/git-2.3.5-intel-universal-snow-leopard.dmg/download) + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo apt-get install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo dnf install git +``` + + + + + +{% filename %}command-line{% endfilename %} + +```bash +$ sudo zypper install git +``` + + \ No newline at end of file diff --git a/fr/installation/README.md b/fr/installation/README.md index d00a4e6805f..f29db8a699a 100644 --- a/fr/installation/README.md +++ b/fr/installation/README.md @@ -1,10 +1,10 @@ # 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). +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. -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. +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. 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. -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. +If you find it useful, you can follow 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. Bonne chance ! @@ -12,6 +12,11 @@ Bonne chance ! 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. + {% include "/chromebook_setup/instructions.md" %} + + + # Installer Python {% include "/python_installation/instructions.md" %} @@ -30,7 +35,7 @@ Pendant l'atelier, vous allez apprendre à construire un blog. Afin d'être prê # Créer un compte GitHub -Allez sur [GitHub.com](https://www.github.com) et créez-vous un nouveau compte gratuitement. +Si vous ne l'avez pas encore fait, allez sur [GitHub.com](https://www.github.com) et créez-vous un nouveau compte gratuitement. # Créer un compte PythonAnywhere @@ -40,10 +45,14 @@ Allez sur [GitHub.com](https://www.github.com) et créez-vous un nouveau compte 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) +* [Comment fonctionne l'Internet ?](../how_the_internet_works/README.md) + +* [Introduction à la ligne de commande](../intro_to_command_line/README.md) + +* [Introduction à Python](../python_introduction/README.md) - * [Introduction à la ligne de commande](../intro_to_command_line/README.md) +* [Qu'est-ce que Django?](../django/README.md) - * [Introduction à Python](../python_introduction/README.md) +# Enjoy the workshop! - * [Qu'est-ce que Django?](../django/README.md) +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. \ No newline at end of file diff --git a/fr/instructions.md b/fr/instructions.md new file mode 100644 index 00000000000..d042926b29a --- /dev/null +++ b/fr/instructions.md @@ -0,0 +1,60 @@ +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 update + sudo apt install python3.6-venv + + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} + + mkdir djangogirls + cd djangogirls + python3.6 -mvenv myvenv + source myvenv/bin/activate + pip install django~=1.11.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). \ No newline at end of file diff --git a/fr/intro_to_command_line/README.md b/fr/intro_to_command_line/README.md index 358d60a21c6..802924f61ec 100755 --- a/fr/intro_to_command_line/README.md +++ b/fr/intro_to_command_line/README.md @@ -1,72 +1,110 @@ # Introduction à l'interface en ligne de commande -C'est un peu exaltant, non ? Dans quelques instants, vous allez écrire votre première ligne de code :) +> 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! :) **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 tout simplement 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 un 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. +> **Note** Please note that throughout this book we use the terms 'directory' and 'folder' interchangeably but they are one and the same thing. ## 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. 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*. +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. It's much like Windows Explorer or Finder on the Mac, but without the graphical interface. On l'appelle parfois aussi : *cmd*, *CLI*, *prompt*, *console* ou *terminal*. ## Ouvrir l'interface en ligne de commande Pour commencer à expérimenter, nous avons d'abord besoin d'ouvrir notre interface en ligne de commande. -### Windows + + +Go to Start menu → Windows System → Command Prompt. + +> On older versions of Windows, look in Start menu → All Programs → Accessories → Command Prompt. + + -Aller dans Menu démarrer → Tous les programmes → Accessoires → Invite de commandes. + -### Mac OS X +Go to Applications → Utilities → Terminal. -Applications → Utilitaires → Terminal. + -### Linux + -Vous la trouverez probablement dans Applications → Accessoires → Terminal, mais ça dépend de votre système. Si elle n'est pas là, demandez à Google :) +Vous la trouverez probablement dans Applications → Accessoires → Terminal, mais ça dépend de votre système. Si elle n'est pas là, demandez à Google. :) + + ## Prompt Vous devriez maintenant voir une fenêtre noire ou blanche qui attend vos commandes. + + Si vous être sous Mac ou Linux, vous verrez probablement un `$`, comme ça : +{% filename %}command-line{% endfilename %} + $ + + + + Sur Windows, c'est un signe `>`, comme ça : +{% filename %}command-line{% endfilename %} + > + + + + +Chaque commande commence par ce signe, puis un espace. Mais vous n'avez pas besoin de le taper, votre ordinateur le fait pour vous. :) +> 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. -Chaque commande commence par ce signe, puis un espace. Mais vous n'avez pas besoin de le taper, votre ordinateur le fait pour vous :) +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. -> 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. +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. ## Votre première commande (YAY !) -Commençons par quelque chose de simple. Tapez la commande suivante : +Let's start by typing this command: + + + +{% filename %}command-line{% endfilename %} $ whoami + + + + -ou +{% filename %}command-line{% endfilename %} > whoami + + Puis, appuyez sur la touche `entrée`. Voilà ce qui s'affiche chez moi : +{% filename %}command-line{% endfilename %} + $ whoami olasitarska + +Comme vous pouvez le voir, l'ordinateur vient d'afficher votre nom d'utilisateur. Sympa, non? :) -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 à les retenir ! +> Try to type each command; do not copy-paste. You'll remember more this way! ## Les bases @@ -76,19 +114,31 @@ Les différents systèmes d'exploitation ont des commandes légèrement différe Ce serait pratique de savoir dans quel répertoire nous nous trouvons. Pour le savoir, tapez la commande suivante et appuyez sur `entrée` : + + +{% filename %}command-line{% endfilename %} + $ pwd /Users/olasitarska + + +> Remarque : "pwd" veut dire "print working directory" (afficher le dossier courant). + + + -Si vous êtes sous Windows : +{% filename %}command-line{% endfilename %} > cd C:\Users\olasitarska + +> Note: 'cd' stands for 'change directory'. With powershell you can use pwd just like on Linux or Mac OS X. -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" (afficher le dossier courant). +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. * * * @@ -96,15 +146,23 @@ Vous verrez probablement quelque chose de similaire sur votre machine. Quand vou Du coup, que pouvons-nous trouver dans ce dossier personnel ? Pour le savoir, essayons ceci : + + +{% filename %}command-line{% endfilename %} + $ ls Applications Bureau Musique Téléchargements ... + + + + -Windows : +{% filename %}command-line{% endfilename %} > dir Directory of C:\Users\olasitarska @@ -113,7 +171,9 @@ Windows : 05/08/2014 07:28 PM Musique 05/08/2014 07:28 PM Téléchargements ... + +> Note: In powershell you can also use 'ls' like on Linux and Mac OS X. * * * @@ -121,29 +181,49 @@ Windows : Maintenant, essayons d'aller sur notre bureau : + + +{% filename %}command-line{% endfilename %} + $ cd Bureau + + + + -Windows : +{% filename %}command-line{% endfilename %} > cd Bureau + + Vérifions que ça a bien changé : + + +{% filename %}command-line{% endfilename %} + $ pwd /Users/olasitarska/Bureau + + -Windows : + + +{% filename %}command-line{% endfilename %} > cd C:\Users\olasitarska\Bureau + + Et voilà ! -> 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. +> 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` key twice to get a list of options. * * * @@ -151,15 +231,25 @@ Et voilà ! Que diriez-vous de créer un répertoire dédié aux exercices sur votre bureau ? Vous pouvez le faire de cette façon : + + +{% filename %}command-line{% endfilename %} + $ mkdir exercices + + -Windows : + + +{% filename %}command-line{% endfilename %} > mkdir exercices + + -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 :) +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, essayez d'appuyer sur les touches `flèche haut` et `flèche bas` pour retrouver les dernières commandes que vous avez tapé. @@ -167,23 +257,33 @@ Cette petite commande crée un dossier nommé `exercices` sur votre bureau. Vous ### Un peu d'exercice ! -Petit défi pour vous : dans votre nouveau dossier `exercices`, créez un dossier appelé `test`. Pour ça, utilisez les commandes `cd` et `mkdir`. +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) #### Solutions : + + +{% filename %}command-line{% endfilename %} + $ cd exercices $ mkdir test $ ls test + + + + -Windows : +{% filename %}command-line{% endfilename %} > cd exercices > mkdir test > dir 05/08/2014 07:28 PM test + + Félicitations ! :) @@ -195,65 +295,114 @@ Supprimons tout ce qu'on vient de faire, histoire d'éviter de laisser du bazar. D'abord, revenons au Bureau : + + +{% filename %}command-line{% endfilename %} + $ cd .. + + -Windows : + - > cd .. +{% filename %}command-line{% endfilename %} + > cd .. + + -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). +Using `..` with the `cd` command will change your current directory to the parent directory (that is, the directory that contains your current directory). Vérifiez où vous êtes : + + +{% filename %}command-line{% endfilename %} + $ pwd /Users/olasitarska/Bureau + + + + -Windows : +{% filename %}command-line{% endfilename %} > cd C:\Users\olasitarska\Bureau + + 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. +> **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. + + + +{% filename %}command-line{% endfilename %} $ rm -r exercices + + + + -Windows : +{% filename %}command-line{% endfilename %} > rmdir /S exercices exercices, Are you sure ? Y + + Et voilà. Pour être sure que le dossier a bien été supprimé, vérifiez : + + +{% filename %}command-line{% endfilename %} + $ ls + + -Windows : + + +{% filename %}command-line{% endfilename %} > dir + + ### Sortir -C'est tout pour le moment ! Vous pouvez 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? :) + + + +{% filename %}command-line{% endfilename %} $ exit + + + + -Windows : +{% filename %}command-line{% endfilename %} > exit + + -Cool, non ? :) +Cool, non? :) ## Résumé @@ -261,20 +410,20 @@ Voici un résumé de quelques commandes utiles : | Commande (Windows) | Commande (Mac OS / Linux) | Description | Exemple | | ------------------ | ------------------------- | --------------------------- | ------------------------------------------------- | -| exit | exit | ferme la fenêtre | **exit** | +| sortir | sortir | ferme la fenêtre | **sortir** | | cd | cd | change le dossier courant | **cd test** | +| cd | pwd | show the current directory | **cd** (Windows) or **pwd** (Mac OS / Linux) | | dir | ls | liste des fichiers/dossiers | **dir** | | copy | cp | copie un fichier | **copy c:\test\test.txt c:\windows\test.txt** | | move | mv | déplace un fichier | **move c:\test\test.txt c:\windows\test.txt** | | mkdir | mkdir | crée un nouveau dossier | **mkdir testdirectory** | -| del | rm | supprime un dossier/fichier | **del c:\test\test.txt** | +| rmdir (or del) | rm | delete a file | **del c:\test\test.txt** | +| rmdir /S | rm -r | delete a directory | **rm -r testdirectory** | 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 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 +Si vous êtes curieuse, [ss64.com](http://ss64.com) contient une référence complète de toutes les commandes pour tous les systèmes d'exploitation. ## Vous êtes prête ? -Nous allons plonger dans Python ! +Nous allons plonger dans Python ! \ No newline at end of file diff --git a/fr/python_installation/README.md b/fr/python_installation/README.md index 47e71cbd43a..cd6f3b1d170 100755 --- a/fr/python_installation/README.md +++ b/fr/python_installation/README.md @@ -4,10 +4,12 @@ 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. 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 ! +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. This is why it looks simpler than other programming languages, but don't worry – Python is also really powerful! # Installation de Python -> **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 ! +> **Note** Si vous utilisez un Chromebook, passez ce chapitre et prenez soin de suivre les instructions de [configuration pour Chromebook](../chromebook_setup/README.md). +> +> **Note** Si vous avez déjà réalisé les étapes d'installation, vous ne devez pas refaire la procédure - vous pouvez passer directement au prochain chapitre! {% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/fr/python_installation/instructions.md b/fr/python_installation/instructions.md index bf25d129da4..2affe3c332a 100644 --- a/fr/python_installation/instructions.md +++ b/fr/python_installation/instructions.md @@ -1,59 +1,106 @@ -> 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) +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA) video. +> +> Cette section repose sur un tutoriel de 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. +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.6, so if you have any earlier version, you will need to upgrade it. -### 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. +First check whether your computer is running a 32-bit version or a 64-bit version of Windows, by pressing the Windows key + Pause/Break key which will open your System info, and look at the "System type" line. 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. -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 : +One thing to watch out for: During the installation, you will notice a window marked "Setup". Make sure you tick the "Add Python 3.6 to PATH" checkbox and click on "Install Now", as shown here: -![N'oubliez pas d'ajouter Python à votre chemin (path)](../python_installation/images/add_python_to_windows_path.png) +![N'oubliez pas d'ajouter Python à votre chemin (path)](../python_installation/images/python-installation-options.png) -### Linux +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 → Windows System → 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.6.x installer fails with an error, you can try either: + +1. install all Windows Updates and try to install Python 3.6 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.6](https://www.python.org/downloads/release/python-346/). + +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." + +Vous devez aller sur le site https://www.python.org/downloads/release/python-361/ et télécharger l'installateur python: + +* Téléchargez le fichier *Mac OS X 64-bit/32-bit installer*, +* Double click *python-3.6.1-macosx10.6.pkg* to run the installer. + + + + 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 : +{% filename %}command-line{% endfilename %} + $ python3 --version - Python 3.4.3 + Python 3.6.1 -Si Python n'est pas installé ou que vous avez une version différente, vous pouvez l'installer en suivant les instructions suivantes : +Si vous avez installé une "micro" version particulière de Python, par exemple la 3.6.0, alors plus besoin de la mettre à niveau. 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 +{% filename %}command-line{% endfilename %} + + $ sudo apt-get install python3.6 -#### Fedora + + + Tapez cette commande dans votre terminal : - $ sudo dnf install python3.4 +{% filename %}command-line{% endfilename %} + + sudo dnf install python3 -#### openSUSE +If you're on older Fedora versions you might get an error that the command `dnf` is not found. In that case, you need to use yum instead. -Tapez cette commande dans votre terminal : + - $ sudo zypper install python3 + + +Tapez cette commande dans votre terminal : +{% filename %}command-line{% endfilename %} -### OS X + $ sudo zypper install python3 + -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. +Verify the installation was successful by opening a command prompt and running the `python3` command: -Vérifiez que l'installation s'est bien déroulée en ouvrant votre *Terminal* et en lançant la commande `python3`: +{% filename %}command-line{% endfilename %} $ python3 --version - Python 3.4.3 + Python 3.6.1 +**NOTE:** If you're on Windows and you get an error message that `python3` wasn't found, try using `python` (without the `3`) and check if it still might be a version of Python 3.6. + * * * -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. +If you have any doubts, or if something went wrong and you have no idea what to do next, please ask your 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. \ No newline at end of file diff --git a/fr/python_introduction/README.md b/fr/python_introduction/README.md index 4e454f5c6e3..800e48c7af4 100755 --- a/fr/python_introduction/README.md +++ b/fr/python_introduction/README.md @@ -1,57 +1,75 @@ # Introduction à Python -> Note : ce chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> Une partie de ce chapitre s’inspire du tutoriel des Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). Allons écrire du code ! ## Le prompt Python -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]. +> 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. - [1]: ../intro_to_command_line/README.md +Pour commencer à jouer avec Python, nous avons besoin d'ouvrir une *ligne de commande* sur votre ordinateur. You should already know how to do that – you learned it in the [Intro to Command Line](../intro_to_command_line/README.md) chapter. Dès que vous êtes prête, suivez les instructions suivantes. Afin d'ouvrir une console Python, tapez `python` sous Windows ou `python3` sous Mac OS/Linux et appuyez sur `entrée`. -```python -$ python3 -Python 3.4.3 (...) -Type "help", "copyright", "credits" or "license" for more information. ->>> -``` +{% filename %}command-line{% endfilename %} + + $ python3 + Python 3.6.1 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + ## Votre première commande Python ! -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. +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. You don't have to type in `>>>` – Python will do that for you. + +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 `>>>`. +For now, we don't want to exit the Python console. We want to learn more about it. Let's start by typing some math, like `2 + 3` and hitting `enter`. -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`. +{% filename %}command-line{% endfilename %} ```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, non ? Vous avez vu comment la réponse a surgi ? Python s'y connait en math ! Vous pouvez essayer d’autres commandes comme : + +- `4 * 5` +- `5 - 1` +- `40 / 2` + +To perform exponential calculation, say 2 to the power 3, we type: {% filename %}command-line{% endfilename %} + +```python +>>> 2 ** 3 +8 +``` -Amusez-vous un peu avec ça, et revenez ici après :). +Amusez-vous un peu avec ça, et revenez ici après. :) -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 ... +As you can see, Python is a great calculator. If you're wondering what else you can do… -## Chaînes de caractères (Strings) +## Chaines de caractères (Strings) Et si nous essayions avec votre nom ? Tapez votre prénom entre guillemets, comme cela : +{% filename %}command-line{% endfilename %} + ```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 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. +Vous venez de créer votre première chaine 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. Çela 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 chaine de caractères. -Il est possible d'assembler des chaînes de caractères comme ceci : +Il est possible d'assembler des chaines de caractères comme ceci : + +{% filename %}command-line{% endfilename %} ```python >>> "Salut " + "Ola" @@ -60,21 +78,27 @@ Il est possible d'assembler des chaînes de caractères comme ceci : Vous pouvez aussi multiplier une chaîne de caractères par un nombre : +{% filename %}command-line{% endfilename %} + ```python >>> "Ola" * 3 'OlaOlaOla' ``` -Si vous avez besoin de mettre une apostrophe dans votre chaîne de caractères, vous avez deux possibilités. +Si vous avez besoin de mettre une apostrophe dans votre chaine de caractères, vous avez deux possibilités. Vous pouvez utiliser des guillemets doubles : +{% filename %}command-line{% endfilename %} + ```python >>> "J'aime la mousse au chocolat" "J'aime la mousse au chocolat" ``` -ou échapper l’apostrophe avec une barre oblique inversée (un backslash, `\`) : +ou échapper l’apostrophe avec une barre oblique inversée (un backslash, ``) : + +{% filename %}command-line{% endfilename %} ```python >>> 'J\'aime la mousse au chocolat' @@ -83,30 +107,34 @@ ou échapper l’apostrophe avec une barre oblique inversée (un backslash, ` Pas mal, non ? Pour voir votre nom en majuscules, tapez juste : +{% filename %}command-line{% endfilename %} + ```python >>> "Ola".upper() 'OLA' ``` -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. +Vous venez d'utiliser la **fonction** `upper` sur votre chaine de caractères! 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! -Si vous voulez savoir combien il y a de lettres dans votre nom, il y a une fonction pour ça ! +{% filename %}command-line{% endfilename %} ```python >>> len("Ola") 3 ``` -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`. +Vous avez peut-être remarqué que parfois, on appelle la fonction avec `.` en la plaçant après la chaine de caractères (comme `"Ola".upper()`) alors qu'à d'autres moment, on appelle d'abord la fonction puis la chaine 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 chaines 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 avons découvert : +OK, assez parlé de chaines 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 * qui combinent des valeurs pour en obtenir de nouvelles -* **les fonctions** - comme upper() et len() qui effectuent des actions sur les objets. +- **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. 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 ! @@ -114,6 +142,8 @@ Ce sont des bases présentes dans tous les langages de programmation que vous po 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` : +{% filename %}command-line{% endfilename %} + ```python >>> len(304023) Traceback (most recent call last): @@ -121,40 +151,48 @@ Traceback (most recent call last): TypeError: object of type 'int' has no len() ``` -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 ? +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 chaine de caractères ? Après tout, les chaînes de caractères ont bien une taille, non ? + +{% filename %}command-line{% endfilename %} ```python >>> len(str(304023)) 6 ``` -Ç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. +Ça a marché ! Nous avons utilisé la fonction `str` à l'intérieur de la fonction `len`. La fonction `str()` convertit n'importe quoi en chaine de caractères. -* La fonction `str` convertit des choses en **chaînes de caractères** -* La fonction `int` convertit des choses en **entiers** +- La fonction `str` convertit des choses en **chaines de caractères** +- La fonction `int` convertit des choses en **entiers** -> 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')` ? +> Important: we can convert numbers into text, but we can't necessarily convert text into numbers – what would `int('hello')` be anyway? ## Variables -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. +Il y 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 que nous aimerions créer une variable appelée `name` : +{% filename %}command-line{% endfilename %} + ```python >>> name = "Ola" ``` -Vous voyez ? C'est tout bête ! C'est simplement : name vaut Ola. +We type name equals 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` : +{% filename %}command-line{% endfilename %} + ```python >>> name 'Ola' ``` -Youpi ! Votre première variable :) ! Vous pouvez toujours changer ce à quoi elle fait référence : +Yippee! Your first variable! :) You can always change what it refers to: + +{% filename %}command-line{% endfilename %} ```python >>> name = "Sonja" @@ -164,12 +202,16 @@ Youpi ! Votre première variable :) ! Vous pouvez toujours changer ce à quoi el Vous pouvez aussi l'utiliser dans des fonctions : +{% filename %}command-line{% endfilename %} + ```python >>> len(name) 5 ``` -Génial, non ? Et bien sûr, les variables peuvent être n'importe quoi, y compris des nombres ! Essayez ça : +Awesome, right? Of course, variables can be anything – numbers too! Try this: + +{% filename %}command-line{% endfilename %} ```python >>> a = 4 @@ -178,7 +220,9 @@ Génial, non ? Et bien sûr, les variables peuvent être n'importe quoi, y compr 24 ``` -Mais que se passe-t-il si nous utilisons le mauvais nom ? Essayez de deviner ! C'est parti ! +Mais que ce passe-t-il si nous utilisons le mauvais nom ? Essayez de deviner ! C'est parti ! + +{% filename %}command-line{% endfilename %} ```python >>> city = "Tokyo" @@ -196,6 +240,8 @@ Jouez un peu avec les variables et essayez de voir ce que vous pouvez faire ! Essayez ça : +{% filename %}command-line{% endfilename %} + ```python >>> name = 'Maria' >>> name @@ -204,29 +250,35 @@ Essayez ça : 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 sympa. +Quand vous tapez `name`, l'interpréteur Python répond avec la *représentation* de la chaine 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 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 -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 :) +En plus des chaines 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 : +{% filename %}command-line{% endfilename %} + ```python >>> [] [] -``` +``` 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 : +{% filename %}command-line{% endfilename %} + ```python >>> lottery = [3, 42, 12, 19, 30, 59] ``` 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à ! +{% filename %}command-line{% endfilename %} + ```python >>> len(lottery) 6 @@ -234,12 +286,16 @@ Voilà, nous avons une liste ! Qu'est ce que nous pourrions en faire ? Commenço Hé oui ! `len()` peut aussi vous donner le nombre d'objets dans une liste. Pratique, non ? Peut-être qu'on peut aussi la trier : +{% filename %}command-line{% endfilename %} + ```python >>> lottery.sort() ``` Ç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é : +{% filename %}command-line{% endfilename %} + ```python >>> print(lottery) [3, 12, 19, 30, 42, 59] @@ -249,13 +305,17 @@ Comme vous pouvez le voir, les nombres de la liste sont maintenant triés du plu Pouvons-nous inverser cet ordre ? Essayons! +{% filename %}command-line{% endfilename %} + ```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 : +If you want to add something to your list, you can do this by typing this command: + +{% filename %}command-line{% endfilename %} ```python >>> lottery.append(199) @@ -265,6 +325,8 @@ Facile, non ? Si vous voulez ajouter quelque chose à la liste, vous pouvez le f 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 : +{% filename %}command-line{% endfilename %} + ```python >>> print(lottery[0]) 59 @@ -274,7 +336,9 @@ Si vous ne souhaitez afficher que le premier nombre, vous pouvez le faire en uti 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. -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. +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. + +{% filename %}command-line{% endfilename %} ```python >>> print(lottery) @@ -282,19 +346,24 @@ Pour supprimer un objet de votre liste, vous aurez besoin de son **indice** ains >>> print(lottery[0]) 59 >>> lottery.pop(0) +59 >>> print(lottery) [42, 30, 19, 12, 3, 199] ``` Ça marche à merveille ! -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 ? +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 ses 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. 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 : +> 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 >>> {} @@ -303,28 +372,34 @@ Un dictionnaire est un peu comme une liste. Cependant, nous utilisons des clefs C'est comme ça que l'on crée un dictionnaire vide. Hourra ! -Maintenant, essayez d'écrire la commande suivante (et essayez aussi de changer le contenu) : +Now, try writing the following command (try substituting your own information, too): + +{% filename %}command-line{% endfilename %} ```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 : +With this command, you just created a variable named `participant` with three key–value pairs: -* 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). +- La clef `name` pointe vers la valeur `'Ola'` (un objet `chaine de caractères`), +- `country` pointe vers `'Poland'` (une autre `chaine 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 : +{% filename %}command-line{% endfilename %} + ```python >>> print(participant['name']) Ola ``` -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. +See, it's similar to a list. But you don't need to remember the index – just the name. -Que se passe-t-il lorsque nous demandons à Python la valeur correspondant à une clef qui n'existe pas ? Pouvez-vous le deviner ? Essayons voir ! +Que ce passe-t-il lorsque nous demandons à Python la valeur correspondant à une clef qui n'existe pas ? Pouvez-vous le deviner ? Essayons voir ! + +{% filename %}command-line{% endfilename %} ```python >>> participant['age'] @@ -337,35 +412,44 @@ Oh, une autre erreur ! Celle-ci est une **KeyError**. Python nous donne un coup 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. +- 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. + +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: -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 : +{% filename %}command-line{% endfilename %} ```python >>> participant['favorite_language'] = 'Python' ``` -Comme pour les listes, la fonction `len()` permet d'obtenir le nombre de paires clef-valeur du dictionnaire. Essayez et tapez la commande suivante : +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: + +{% filename %}command-line{% endfilename %} ```python >>> len(participant) 4 ``` -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. +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 `pop()` method to delete an item in the dictionary. 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 : +{% filename %}command-line{% endfilename %} ```python >>> participant.pop('favorite_numbers') +[7, 42, 92] >>> participant {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} ``` -Comme vous pouvez le voir dans votre console, la paire clef-valeur correspondant à "favorite_numbers" a été supprimée. +As you can see from the output, the key–value pair corresponding to the 'favorite_numbers' key has been deleted. -De même, vous pouvez changer la valeur associée à une clef déjà créée dans le dictionnaire. Tapez ceci : +As well as this, you can also change a value associated with an already-created key in the dictionary. Type this: + +{% filename %}command-line{% endfilename %} ```python >>> participant['country'] = 'Germany' @@ -373,22 +457,26 @@ De même, vous pouvez changer la valeur associée à une clef déjà créée dan {'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 ! +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. ### Résumé 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 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 +- **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 On continue ? :) ## Comparer des choses -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 : +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. + +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: + +{% filename %}command-line{% endfilename %} ```python >>> 5 > 2 @@ -403,12 +491,14 @@ True True ``` -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 ? +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? -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. +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. You always, **always** need to put two of them – `==` – if you want to check if things are equal to each other. 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 : +{% filename %}command-line{% endfilename %} + ```python >>> 6 >= 12 / 2 True @@ -416,15 +506,17 @@ True False ``` -`>` et `<` sont faciles, mais qu'est ce que `>=` et `<=` veulent dire ? Ils se lisent comment ça : +We've seen `>` and `<`, but what do `>=` and `<=` mean? Read them like this: -* 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 +- 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 : +{% filename %}command-line{% endfilename %} + ```python >>> 6 > 2 and 2 < 3 True @@ -436,30 +528,37 @@ True Vous pouvez donner à Python autant de nombres à comparer que vous le souhaitez et il vous donnera une réponse. Plutôt malin, non ? -* **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 +- **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 Vous connaissez l'expression "on ne compare pas les choux et les carottes" ? Essayons l'équivalent en Python : +{% filename %}command-line{% endfilename %} + ```python >>> 1 > 'django' Traceback (most recent call last): File "", line 1, in -TypeError: unorderable types: int() > str() +TypeError: '>' not supported between instances of 'int' and 'str' ``` -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. +Comme vous le voyez, Python n'est pas capable de comparer un nombre (`int`) et une chaine 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**. C'est probablement le type le plus simple qui existe. +Incidentally, you just learned about a new type of object in Python. It's called **Boolean**. -Il n'y a que deux objets Booléens : - True (vrai) - False (faux) +There are only two Boolean objects: -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.) +- True +- False + +But for Python to understand this, you need to always write it as 'True' (first letter uppercase, with the rest of the letters lowercased). **true, TRUE, and tRUE won't work – only True is correct.** (The same applies to 'False' as well, of course.) Les Booléens aussi peuvent être des variables ! regardez : +{% filename %}command-line{% endfilename %} + ```python >>> a = True >>> a @@ -468,31 +567,37 @@ True Vous pouvez aussi faire ça : +{% filename %}command-line{% endfilename %} + ```python >>> a = 2 > 5 >>> a False ``` -Entrainez-vous et amusez-vous avec les Booleéns en essayant de lancer les commandes suivantes : +Entraînez-vous et amusez-vous avec les Booleéns en essayant de lancer les commandes suivantes : -* `True and True` -* `False and True` -* `True or 1 == 1` -* `1 != 2` +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` 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 ! +> 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. + 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 -* Le lancer ! +- Quitter l'interpréteur Python +- Ouvrir l'éditeur de code de notre choix +- 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()` : +To exit from the Python interpreter that we've been using, simply type the `exit()` function + +{% filename %}command-line{% endfilename %} ```python >>> exit() @@ -501,87 +606,140 @@ $ Cela vous ramènera dans la ligne de commande de votre 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](../code_editor/README.md), 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 +{% filename %}editor{% endfilename %} ```python 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 :) - 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. 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. +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**. The **.py** extension tells our operating system that this is a **Python executable file** and Python can run it. + +> **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. C'est ce qu'on appelle « la coloration syntaxique ». C'est une fonctionnalité très utile lorsque l'on programme. 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). C'est ce genre de fonctionnalités qui font que vous aimerez rapidement programmer avec un éditeur de code. :) 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 à : +{% filename %}command-line{% endfilename %} + $ cd ~/Desktop + + + + -Sous Linux, comme ça (il se peut que le mot Bureau soit dans une autre langue) : +On Linux, it will be like this (the word "Desktop" might be translated to your local language): + +{% filename %}command-line{% endfilename %} $ cd ~/Desktop + + + + -Et sous Windows, ce sera comme ça : +On Windows Command Prompt, it will be like this: + +{% filename %}command-line{% endfilename %} > cd %HomePath%\Desktop + + + + + +And on Windows Powershell, it will be like this: + +{% filename %}command-line{% endfilename %} + + > cd $Home\Desktop + + + Si vous êtes bloquée, n'hésitez pas à appeler à l'aide. Maintenant, utilisez Python pour exécuter le code contenu dans votre fichier : +{% 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: +{% filename %}command-line{% endfilename %} + +```python +> python python_intro.py +``` 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 +## If … elif … else -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). +Lots of things in code should be executed only when given conditions are met. That's why Python has something called **if statements**. Remplacez le code dans votre fichier **python_intro.py** avec ceci : +{% filename %}python_intro.py{% endfilename %} + ```python if 3 > 2: ``` -Si nous sauvegardons ce fichier et que nous le lançons, nous obtiendrons l'erreur suivante : +If we were to save and run this, we'd see an error like this: -```python -$ 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 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 : +{% filename %}python_intro.py{% endfilename %} + ```python if 3 > 2: - print('It works!') + print('Ça marche !') ``` 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 ! +{% filename %}command-line{% endfilename %} + +```python +$ python3 python_intro.py +Ça marche ! +``` +Note: Remember that on Windows, 'python3' is not recognized as a command. From now on, replace 'python3' with 'python' to execute the file. ### Et que se passe-t-il si une condition n’est pas vraie ? 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) : +{% filename %}python_intro.py{% endfilename %} + ```python if 5 > 2: print('5 est effectivement plus grand que 2') @@ -591,11 +749,15 @@ else: Lorsque vous exécuterez le code, ceci s'affichera : +{% filename %}command-line{% endfilename %} + $ python3 python_intro.py 5 est effectivement plus grand que 2 + +If 2 were a greater number than 5, then the second command would be executed. Let's see how `elif` works: -Et si 2 était plus grand que 5, la seconde commande serait exécutée. Facile, non ? Voyons comment `elif` fonctionne : +{% filename %}python_intro.py{% endfilename %} ```python name = 'Sonja' @@ -609,52 +771,80 @@ else: Exécutons le code : +{% filename %}command-line{% endfilename %} + $ python3 python_intro.py Hey Sonja! - + 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 : +{% filename %}python_intro.py{% endfilename %} + ```python volume = 57 if volume < 20: - print("C'est plutôt calme.") + print("It's kinda quiet.") elif 20 <= volume < 40: - print("Une jolie musique de fond.") + print("It's nice for background music") elif 40 <= volume < 60: - print("Parfait, je peux entendre tous les détails du morceau.") + print("Perfect, I can hear all the details") elif 60 <= volume < 80: - print("Parfait pour faire la fête !") + print("Nice for parties") elif 80 <= volume < 100: - print("Un peu trop fort !") + print("A bit loud!") else: - print("Au secours ! Mes oreilles ! :(") + print("My ears are hurting! :(") ``` Python va tester les différentes conditions puis il affichera ceci : +{% filename %}command-line{% endfilename %} + $ python3 python_intro.py Parfait, je peux entendre tous les détails du morceau. + + +## 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. ### Résumé -Avec ces trois derniers exercices, vous avez appris : +In the last few exercises you learned about: -* **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` -* **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. +- **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 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 à écrire vos propres fonctions! +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. + +Remember functions like `len()` that you can execute in Python? Well, good news – you will learn how to write your own functions now! + +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. Let's give it a go. Remplacer le code de **python_intro.py** par ceci : -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 : +{% filename %}python_intro.py{% endfilename %} ```python def hi(): @@ -670,12 +860,22 @@ Vous vous demandez peut-être pourquoi nous avons écrit le nom de la fonction Lançons notre code pour voir ce qui se passe : +{% filename %}command-line{% endfilename %} + $ python3 python_intro.py Hi there! How are you? + + +Note: if it didn't work, don't panic! The output will help you to figure why: +- If you get a `NameError`, that probably means you typed something wrong, so you should check that you used the same name when creating the function with `def hi():` and when calling it with `hi()`. +- If you get an `IndentationError`, check that both of the `print` lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned. +- If there's no output at all, check that the last `hi()` *isn't* indented - if it is, that line will become part of the function too, and it will never get run. -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 : +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): @@ -683,6 +883,8 @@ def hi(name): Comme vous le voyez, nous avons donné à notre fonction un paramètre appelé `name` : +{% filename %}python_intro.py{% endfilename %} + ```python def hi(name): if name == 'Ola': @@ -697,46 +899,59 @@ hi() 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 : -```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' -``` +{% 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' + 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 : +{% filename %}python_intro.py{% endfilename %} + ```python hi("Ola") ``` -Et exécutez votre code à nouveau : +Et relançons le : + +{% filename %}command-line{% endfilename %} $ python3 python_intro.py Hi Ola! - + Et que se passe-t-il quand on change de nom ? +{% filename %}python_intro.py{% endfilename %} + ```python hi("Sonja") ``` -Exécutez votre code à nouveau : +Et qu'on le lance : + +{% 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: -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 : +{% filename %}command-line{% endfilename %} Hi anonymous! + +Super, non ? Avec ça, vous n'avez pas besoin de vous répéter lorsque vous voulez changer le nom de la personne à saluer. And that's exactly why we need functions – you never want to repeat your code! -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 ! +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? -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 ? +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): @@ -747,34 +962,44 @@ hi("Rachel") Exécutons à nouveau notre code : +{% filename %}command-line{% endfilename %} + $ python3 python_intro.py Hi Rachel! + - -Félicitations ! Vous venez juste d’apprendre à écrire des fonctions ! :) +Bravo ! Vous venez d'apprendre à écrire des fonctions! :) ## Les boucles +> For readers at home: this part is covered in the [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) video. + C’est déjà la dernière partie. C’était rapide, non ? :) 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 : +{% filename %}python_intro.py{% endfilename %} + ```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 : +{% filename %}python_intro.py{% endfilename %} + ```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. +The ```for``` statement behaves similarly to the ```if``` statement; code below both of these need to be indented four spaces. Voilà le code complet à mettre dans votre fichier : +{% filename %}python_intro.py{% endfilename %} + ```python def hi(name): print('Hi ' + name + '!') @@ -787,6 +1012,8 @@ for name in girls: Exécutez votre code : +{% filename %}command-line{% endfilename %} + $ python3 python_intro.py Hi Rachel! Next girl @@ -798,12 +1025,14 @@ Exécutez votre code : Next girl Hi You! Next girl - + 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`. Vous pouvez aussi utiliser `for` sur des nombres grâce à la fonction `range`: +{% filename %}python_intro.py{% endfilename %} + ```python for i in range(1, 6): print(i) @@ -811,23 +1040,23 @@ for i in range(1, 6): Ce qui affiche : +{% filename %}command-line{% endfilename %} + 1 2 3 4 5 - + `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. +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'inclue pas 6). That is because "range" is half-open, and by that we mean it includes the first value, but not the last. ## Résumé -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 ! - -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 :) +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ère de vous ! -![Cupcake][3] +You might want to briefly do something else – stretch, walk around for a bit, rest your eyes – before going on to the next chapter. :) - [3]: images/cupcake.png +![Cupcake](images/cupcake.png) \ No newline at end of file diff --git a/fr/signup_pythonanywhere.md b/fr/signup_pythonanywhere.md new file mode 100644 index 00000000000..66b0ffcac05 --- /dev/null +++ b/fr/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Next it's time to sign up for a free "Beginner" account on PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** When choosing your username here, bear in mind that your blog's URL will take the form `yourusername.pythonanywhere.com`, so choose either your own nickname, or a name for what your blog is all about. \ No newline at end of file diff --git a/fr/template_extending/README.md b/fr/template_extending/README.md index 91d2dc08572..64d4fb28de2 100755 --- a/fr/template_extending/README.md +++ b/fr/template_extending/README.md @@ -2,9 +2,9 @@ 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 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! +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! -## Créer un template de base +## Create a base template Un template de base est le template le plus simple que vous pouvez faire hériter à chaque page de votre site web. @@ -15,10 +15,12 @@ Créons le fichier `base.html` dans le dossier `blog/templates/blog/` : └───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 : +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html {% load staticfiles %} @@ -55,6 +57,8 @@ Ensuite, ouvrez ce fichier `base.html` et collez-y tout ce qui se trouve dans le Puis, dans le fichier `base.html`, remplacez tout ce qui se trouve dans `` (de `` à ``) par ceci : +{% filename %}blog/templates/blog/base.html{% endfilename %} + ```html