Skip to content

Commit 2f6b0ee

Browse files
committed
resolving a merge conflict...
2 parents d70993d + 640bf06 commit 2f6b0ee

14 files changed

Lines changed: 316 additions & 75 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ It will (more or less) look like this:
2626

2727
![Figure 0.1](images/application.png)
2828

29-
Ok, [let's start at the beginning...](how_internet_works/README.md)
29+
OK, [let's start at the beginning...](how_internet_works/README.md)
3030

3131
## About and contributing
3232

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Summary
22

33
* [How the Internet works?](how_internet_works/README.md)
4+
* [Intro to Command Line](intro_to_command_line/README.md)
45
* [Python installation](python_installation/README.md)
56
* [Introduction to Python](python_introduction/README.md)
67
* [What is Django?](django/README.md)
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Security
2+
3+
You might have noticed that you didn't have to use your password apart from back when we used the admin-interface. And you might notice that this means that everyone can add or edit posts in your blog. I don't know about you, but I don't want just anyone to post on my blog. So lets do something about it.
4+
5+
## Authorizing add/edit of posts
6+
7+
First lets make things secure. We will protect our `post_new`, `post_edit` and `post_publish` views so that only logged-in users can access them. Django ships with some nice helpers for that using a kind-of advanced topic of _decorators_. Don't worry about the technicalities now, you can read up on these later. The decorator to use is shipped in Django in a module `django.contrib.auth.decorators` and is named `login_required`.
8+
9+
So edit your `mysite/views.py` and add these lines at the top where all the imports are:
10+
11+
```
12+
from django.contrib.auth.decorators import login_required
13+
```
14+
15+
Then add a line before each of the `post_new`, `post_edit` and `post_publish` like the following:
16+
17+
```
18+
@login_required
19+
def post_new(request):
20+
[...]
21+
```
22+
23+
Thats it! Now try again to access `http://localhost:8000/post/new/`, notice the difference?
24+
25+
> If you just got the empty form, you are probably still logged in from the chapter on the admin-interface. Go to `http://localhost:8000/admin/logout/` to log out, then goto `http://localhost:8000/post/new` again.
26+
27+
You should get one of the beloved errors again. This one is quite interesting actually: The decorator we added before will redirect you to the login page. But that isn't available yet, so it raises a "Page not found (404)".
28+
29+
Don't forget to add the decorator from above to `post_edit` and `post_publish` too.
30+
31+
Horray, we reached part of the goal! Other people can't just create posts on our blog anymore. Unfortunately we can't create posts anymore too. So lets fix that next.
32+
33+
## Login users
34+
35+
Now we could try to do lots of magic stuff to implement users and passwords and authentication but doing this kind of stuff right is rather complicated. And as Django is "batteries included", we will make further use of the authentication stuff provided.
36+
37+
In your `mysite/urls.py` add an url `url(r'^accounts/login/$', 'django.contrib.auth.views.login')`. So the file should now look similar to this:
38+
39+
```
40+
from django.conf.urls import patterns, include, url
41+
42+
from django.contrib import admin
43+
admin.autodiscover()
44+
45+
urlpatterns = patterns('',
46+
url(r'^admin/', include(admin.site.urls)),
47+
url(r'^accounts/login/$', 'django.contrib.auth.views.login'),
48+
url(r'', include('blog.urls')),
49+
)
50+
```
51+
52+
Then we need a template for the login-page, so create a directory `mysite/templates/registration` and a file inside named `login.html`:
53+
54+
```
55+
{% extends "mysite/base.html" %}
56+
57+
{% block content %}
58+
59+
{% if form.errors %}
60+
<p>Your username and password didn't match. Please try again.</p>
61+
{% endif %}
62+
63+
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
64+
{% csrf_token %}
65+
<table>
66+
<tr>
67+
<td>{{ form.username.label_tag }}</td>
68+
<td>{{ form.username }}</td>
69+
</tr>
70+
<tr>
71+
<td>{{ form.password.label_tag }}</td>
72+
<td>{{ form.password }}</td>
73+
</tr>
74+
</table>
75+
76+
<input type="submit" value="login" />
77+
<input type="hidden" name="next" value="{{ next }}" />
78+
</form>
79+
80+
{% endblock %}
81+
```
82+
83+
You will see that this also makes use of our base-template for the overall look and feel of your blog.
84+
85+
The nice thing here is that this _just works[TM]_. We don't have to deal with handling of the forms submission nor with passwords and securing them. Only one thing is left here, we should add a setting to `mysite/settings.py`:
86+
87+
```
88+
LOGIN_REDIRECT_URL = '/'
89+
```
90+
91+
Now when the login is accessed directly, it will redirect successful login to the top level index.
92+
93+
## Improving the layout
94+
95+
So now we made sure that only authorized users (ie. us) can add, edit or publish posts. But still everyone gets to view the buttons to add or edit posts, lets hide these for users that aren't logged in. For this we need to edit the templates, so lets start with the base template from `mysite/templates/mysite/base.html`:
96+
97+
```
98+
<body>
99+
<div class="page-header">
100+
{% if user.is_authenticated %}
101+
<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
102+
<a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a>
103+
{% else %}
104+
<a href="{% url 'django.contrib.auth.views.login' %}" class="top-menu"><span class="glyphicon glyphicon-lock"></span></a>
105+
{% endif %}
106+
<h1><a href="{% url 'blog.views.post_list' %}">Django Girls</a></h1>
107+
</div>
108+
<div class="content">
109+
<div class="row">
110+
<div class="col-md-8">
111+
{% block content %}
112+
{% endblock %}
113+
</div>
114+
</div>
115+
</div>
116+
</body>
117+
```
118+
119+
You might recognize the pattern here. There is an if-condition inside the template that checks for authenticated users to show the edit-buttons. Otherwise it shows a login button.
120+
121+
*Homework*: Edit the template `blog/templates/blog/post_detail.html` to only show the edit-buttons for authenticated users.
122+
123+
## More on authenticated users
124+
125+
Lets add some nice sugar to our templates while we are at it. First we will add some stuff to show that we are logged in. Edit `mysite/templates/mysite/base.html` like this:
126+
127+
```
128+
<div class="page-header">
129+
{% if user.is_authenticated %}
130+
<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
131+
<a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a>
132+
<p class="top-menu">Hello {{ user.username }}<small>(<a href="{% url 'django.contrib.auth.views.logout' %}">Log out</a>)</p>
133+
{% else %}
134+
<a href="{% url 'django.contrib.auth.views.login' %}" class="top-menu"><span class="glyphicon glyphicon-lock"></span></a>
135+
{% endif %}
136+
<h1><a href="{% url 'blog.views.post_list' %}">Django Girls</a></h1>
137+
</div>
138+
```
139+
140+
This adds a nice "Hello &lt;username&gt;" to remind us who we are and that we are authenticated. Also this adds link to log out of the blog. But as you might notice this isn't working yet. Oh nooz, we broke the internez! Lets fix it!
141+
142+
We decided to rely on django to handle log-in, lets see if Django can also handle log-out for us. Check https://docs.djangoproject.com/en/1.6/topics/auth/default/ and see if you find something.
143+
144+
Done reading? You should by now think about adding a url (in `mysite/urls.py`) pointing to the `django.contrib.auth.views.logout` view. Like that:
145+
146+
```
147+
from django.conf.urls import patterns, include, url
148+
149+
from django.contrib import admin
150+
admin.autodiscover()
151+
152+
urlpatterns = patterns('',
153+
url(r'^admin/', include(admin.site.urls)),
154+
url(r'^accounts/login/$', 'django.contrib.auth.views.login'),
155+
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}),
156+
url(r'', include('blog.urls')),
157+
)
158+
```
159+
160+
Thats it! If you followed all of the above until this point (and did the homework), you now have a blog where you
161+
162+
- need username and password to log in,
163+
- need to be logged in to add/edit/publish(/delete) posts
164+
- and can log out again
165+
166+
Treat yourself to a drink now because now your page is both great and secured!

css/README.md

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Our blog still looks pretty ugly, right? Time to make it nice! We will use CSS f
66

77
Cascading Style Sheets (CSS) is a style sheet language used for describing the look and formatting of a website written in markup language (like HTML). Treat it as a make-up for our webpage ;).
88

9-
But we don't want to start from scratch again, right? We will, again, use something that has already been done by programmers and released in the Internet for free. You know, inventing a wheel once again is no fun.
9+
But we don't want to start from scratch again, right? We will, again, use something that has already been done by programmers and released in the Internet for free. You know, reinventing the wheel is no fun.
1010

1111
## Let's use Bootstrap!
1212

@@ -16,13 +16,14 @@ It was written by programmers who worked for Twitter and is now developed by vol
1616

1717
## Install Boostrap
1818

19-
To install Bootstrap, you need to add this to your `<head>` in you `.html` file (`blog/templates/blog/post_list.html`):
19+
To install Bootstrap, you need to add this to your `<head>` in your `.html` file (`blog/templates/blog/post_list.html`):
2020

2121
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
2222
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
2323
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
2424

25-
Then just go ahead, open your website and refresh page. Here it is!
25+
This doesn't add any files to your project. It just points to files that exist on the internet.
26+
Just go ahead, open your website and refresh the page. Here it is!
2627

2728
![Figure 14.1](images/bootstrap1.png)
2829

@@ -41,19 +42,17 @@ First, we need to create a folder to store our static files in. Go ahead and cre
4142
static
4243
manage.py
4344

44-
Now we need to tell Django how it can find it. Open up the `mysite/settings.py` file, scroll to the bottom of it and add the following lines:
45+
Now we need to tell Django where it can find it. Open up the `mysite/settings.py` file, scroll to the bottom of it and add the following lines:
4546

4647
STATICFILES_DIRS = (
4748
os.path.join(BASE_DIR, "static"),
4849
)
4950

5051
This way Django will know where your static files are.
5152

52-
That's it! Time to see if it works :)
53-
5453
## Your first CSS file!
5554

56-
First things first: let's create a CSS file now. Create a new folder called `css` inside your `static` folder. Then create a new file called `blog.css` inside this `css` directory. Ready?
55+
Let's create a CSS file now, to add your own style to your web-page. Create a new folder called `css` inside your `static` folder. Then create a new file called `blog.css` inside this `css` directory. Ready?
5756

5857
static
5958
└───css
@@ -63,21 +62,27 @@ Time to write some CSS! Open up the `static/css/blog.css` file in your code edit
6362

6463
We won't be going too deep into customizing and learning about CSS here, because it's pretty easy and you can learn it on your own after this workshop. We really recommend doing this [Codeacademy HTML & CSS course](http://www.codecademy.com/tracks/web) to learn everything you need to know about making your websites more pretty with CSS.
6564

66-
But let's do at least a little. Maybe we could change the color of our header? To understand colors, computer use special codes. They start with `#` and are followed by 6 letters (A-F) and numbers (0-9). You can find color codes for example here: http://www.colorpicker.com/
65+
But let's do at least a little. Maybe we could change the color of our header? To understand colors, computers use special codes. They start with `#` and are followed by 6 letters (A-F) and numbers (0-9). You can find color codes for example here: http://www.colorpicker.com/. You may also use [predefined colors](http://www.w3schools.com/cssref/css_colornames.asp), such as `red` and `green`.
6766

6867
In your `static/css/blog.css` file you should add following code:
6968

7069
h1 a {
7170
color: #FCA205;
7271
}
7372

74-
`a` inside of `h1` (i.e. when we have in code something like: `<h1><a href="">link</a></h1>`) is the tag we're applying our styles to, and we're telling it to change color to `#FCA205`. Of course, you can put your own color here!
73+
`h1 a` is a CSS Selector. `a` element inside of `h1` element (i.e. when we have in code something like: `<h1><a href="">link</a></h1>`) is the tag we're applying our styles to, and we're telling it to change color to `#FCA205`, which is orange. Of course, you can put your own color here!
74+
75+
In a CSS file we determine styles for elements in the HTML file. The elements are identified by the element name (i.e. `a`, `h1`, `body`), the element class or the element id. Class and id are names you give the element by yourself. Classes define groups of elements, and ids point out to specific elements. For example, the following tag may be identified by CSS using the tag name `a`, the class `external_link`, or the id `link_to_wiki_page`:
76+
77+
<a href="http://en.wikipedia.org/wiki/Django" class="external_link" id="link_to_wiki_page">
78+
79+
Read about [CSS Selectors in w3schools](http://www.w3schools.com/cssref/css_selectors.asp).
7580

7681
Then, we need to also tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file and add this line at the very beginning of it:
7782

7883
{% load staticfiles %}
7984

80-
We're just loading static files here :). Then, between the `<head>` and `</head>` add this line:
85+
We're just loading static files here :). Then, between the `<head>` and `</head>`, after the links to the Bootstrap CSS files (the browser reads the files in the order they're given, so code in our file may override code in Bootstrap files), add this line:
8186

8287
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
8388

@@ -90,8 +95,8 @@ Your file should look like this at this point:
9095
<head>
9196
<title>Django Girls blog</title>
9297
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
93-
<link rel="stylesheet" href="proxy.php?url=https%3A%2F%2Fmaxcdn.bootstrapcdn.com%2Fbootstrap%2F3.2.0%2Fcss%2Fbootstrap-theme.min.css">
94-
<script src="proxy.php?url=https%3A%2F%2Fmaxcdn.bootstrapcdn.com%2Fbootstrap%2F3.2.0%2Fjs%2Fbootstrap.min.js"></script>
98+
<link rel="stylesheet" href="proxy.php?url=https%3A%2F%2Fmaxcdn.bootstrapcdn.com%2Fbootstrap%2F3.2.0%2Fcss%2Fbootstrap-theme.min.css">
99+
<script src="proxy.php?url=https%3A%2F%2Fmaxcdn.bootstrapcdn.com%2Fbootstrap%2F3.2.0%2Fjs%2Fbootstrap.min.js"></script>
95100
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
96101
</head>
97102
<body>
@@ -127,7 +132,7 @@ Maybe we can customize the font in our header? Paste this into your `<head>` in
127132

128133
This line will import a font called *Lobster* from Google Fonts (https://www.google.com/fonts).
129134

130-
Now add this line in `static/css/blog.css` and refresh the page:
135+
Now add the line `font-family: 'Lobster';` in the CSS file `mysite/static/css/blog.css` inside the `h1 a` declaration block (the code between the braces `{` and `}`) and refresh the page:
131136

132137
h1 a {
133138
color: #FCA205;
@@ -138,7 +143,8 @@ Now add this line in `static/css/blog.css` and refresh the page:
138143

139144
Great!
140145

141-
CSS has a concept of classes, which basically allows you to name a part of our HTML code and apply styles only to this part, not affecting others. It's super helpful if you have two divs, but they're doing something very different (like your header and your post), so you don't want them to look the same.
146+
147+
As mentioned above, CSS has a concept of classes, which basically allows you to name a part of the HTML code and apply styles only to this part, not affecting others. It's super helpful if you have two divs, but they're doing something very different (like your header and your post), so you don't want them to look the same.
142148

143149
Go ahead and name some parts of the HTML code. Add a class called `page-header` to your `div` that contains header, like this:
144150

@@ -154,7 +160,7 @@ And now add a class `post` to your `div` containing blogposts.
154160
<p>{{ post.text }}</p>
155161
</div>
156162

157-
All right. We have only one day, so we need to speed things up a little! We can't explain you every little detail about CSS. For now just copy and paste following code into your `static/css/blog.css` file:
163+
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 to help you understand the following code. For now, just copy and paste it into your `mysite/static/css/blog.css` file:
158164

159165
.page-header {
160166
background-color: #ff9400;
@@ -204,7 +210,7 @@ All right. We have only one day, so we need to speed things up a little! We can'
204210
color: #000000;
205211
}
206212

207-
Then also replace this:
213+
Then surround the HTML code which desplayes the posts with declarations of classes. Replace this:
208214

209215
{% for post in posts %}
210216
<div class="post">
@@ -238,7 +244,7 @@ Wohoo! Looks awesome, right? The code we just pasted is not really so hard to un
238244

239245
Don't be afraid to tinker with this CSS a little bit and try to change some things. If you break something, don't worry, you can always undo this!
240246

241-
Anyway, we really recommend taking this free online [Codeacademy HTML & CSS course](http://www.codecademy.com/tracks/web) as a post-workshop homework to learn everything you need to know about making your websites more pretty with CSS.
247+
Anyway, we really recommend taking this free online [Codeacademy HTML & CSS course](http://www.codecademy.com/tracks/web) as a post-workshop homework to learn everything you need to know about making your websites prettier with CSS.
242248

243249
Ready for next chapter?! :)
244250

deploy/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ But first, Heroku needs us to install the `django-toolbelt` package. Go to your
1414

1515
(myvenv) $ pip install dj-database-url gunicorn whitenoise
1616

17-
After the installation is finished, run this command:
17+
After the installation is finished, go to the `mysite` directory and run this command:
1818

1919
(myvenv) $ pip freeze > requirements.txt
2020

2121
This will create a file called `requirements.txt` with a list of your installed packages (i.e. Python libraries that you are using, for example Django :)).
2222

2323
Open this file and add the following line at the bottom:
24-
24+
2525
pyscopg2==2.5.3
2626

2727
This line is needed for your application to work on Heroku.
@@ -73,7 +73,7 @@ Another thing we need to do is modify our website's `settings.py` file. Open `my
7373
ALLOWED_HOSTS = ['*']
7474

7575
STATIC_ROOT = 'staticfiles'
76-
76+
7777
DEBUG = False
7878

7979
At the end of the `mysite/settings.py`, copy and paste this:
@@ -90,7 +90,7 @@ Then save the file.
9090
## mysite/wsgi.py
9191

9292
Open the `mysite/wsgi.py` file and add these lines at the end:
93-
93+
9494
from whitenoise.django import DjangoWhiteNoise
9595
application = DjangoWhiteNoise(application)
9696

django_installation/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ Creating a `virtualenv` on both Linux and OS X is as simple as running:
3838

3939
~/djangogirls$ python3 -m venv myvenv
4040

41+
42+
> __NOTE:__ Initiating the virtual environment on Ubuntu 14.04 like this currently gives the following error:
43+
44+
> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1
45+
46+
> To get around this, use the `virtualenv` command instead.
47+
48+
> ~/djangogirls$ sudo apt-get install python-virtualenv
49+
> ~/djangogirls$ virtualenv myvenv
50+
51+
4152
## Working with virtualenv
4253

4354
The command above will create a folder called `myvenv` that contains our virtual environment (basically bunch of folders and files). All we want to do now is starting it by running:
@@ -50,6 +61,12 @@ on Windows, or:
5061

5162
on OS X and Linux.
5263

64+
> __NOTE:__ sometimes `source` might not be available. In those cases try doing this instead:
65+
66+
> ~/djangogirls$ . myvenv/bin/activate
67+
68+
69+
5370
You will know that you have `virtualenv` started when you see that the prompt in your console looks like:
5471

5572
(myvenv) C:\Users\Name\djangogirls>

0 commit comments

Comments
 (0)