Skip to content

Commit 3bfb12c

Browse files
authored
new release (#427)
* add flake8 to tests. * pep8 police * move flake8 config to .flake8 * fix pep8 args * add python3.5 and 3.6 to travis-ci * speed up tests * Add a general word-wrap style rule * Use docker image from dockerhub. Makefile with command alias * Adds gender field to EventRegistration model * Adds migration related to new gender field * Adds gender field to corresponding forms * Show the gender in registered list and CSV. * fix pep8 * Change the homepage context * Replaces Ultimas Noticias and Últmos Trabajos with a new section * Refactor the homepage as a class-based view * Added factories for testing * Added tests for the new homepage * Sanitize html inputs on Events and Jobs (#412) * fix autosuggest js on jobs form * refs #409 #410 add html_sanitizer to description field of Job and Event * refs #409 410 add tests to Job and Event views * remove duplicate requeriment * adjust code to pycodestyle * fix wrong exception class * Update job_form.html * added normalize_tags function on job utils (#418) * 407 migration to fix tags (#419) * Arreglo error de linter * Added new makemigrations shortcut * added missing migration * Adds a migration to clean the tags * split function to use ir * Use tag normalization function in migration * #346 autoslug (#420) * added autoslug fields to events * fixed url position * Fixed migrations (#423) * Resolviendo issue #383 (#425) * Resolviendo issue #383 Agregue el EMAIL_CONFIRMATION_LA_DOMAIN con el valor "python.org.ar". Probado en un servidor debug funciona correctamente el link. * arreglando error de flake8 * 417 sponsored jobs (#424) * Added rank for pycompanies, updated joblist view with sponsored jobs, added ac.civil badget to pycompanies * Changes after code review * moved css styles and other html stuff * Fixed typo and added one test with rank==0
1 parent d904197 commit 3bfb12c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+846
-97
lines changed

.flake8

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[flake8]
2+
max-line-length=99
3+
exclude=migrations, .git, build.sh

.travis.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ sudo: false
44

55
python:
66
- "3.4"
7+
- "3.5"
8+
- "3.6"
79

810
service:
911
- postgresql
@@ -15,7 +17,9 @@ env:
1517
- DJANGO=1.8 SECRET_KEY=supersecret DB_PORT=5432 DB_SERVICE=localhost DB_PASS="" DB_USER=postgres DB_NAME=postgres
1618

1719
install:
20+
- pip install pip -U
1821
- pip install -r dev_requirements.txt
1922

2023
script:
21-
- python manage.py test
24+
- flake8
25+
- python3 manage.py test -v2 --noinput

Makefile

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
help:
2+
@echo "help -- print this help"
3+
@echo "start -- start docker stack"
4+
@echo "stop -- stop docker stack"
5+
@echo "ps -- show status"
6+
@echo "clean -- clean all artifacts"
7+
@echo "test -- run tests using docker"
8+
@echo "dockershell -- run bash inside docker"
9+
@echo "shell_plus -- run django shell_plus inside docker"
10+
@echo "bootstrap --build containers, run django migrations, load fixtures and create the a superuser"
11+
12+
start:
13+
docker-compose up
14+
15+
stop:
16+
docker-compose stop
17+
18+
ps:
19+
docker-compose ps
20+
21+
clean: stop
22+
docker-compose rm --force -v
23+
24+
only_test:
25+
docker-compose run --rm web python3 ./manage.py test -v2 --noinput
26+
27+
pep8:
28+
docker-compose run --rm web flake8
29+
30+
test: pep8 only_test
31+
32+
dockershell:
33+
docker-compose run --rm web /bin/bash
34+
35+
migrations:
36+
docker-compose run --rm web python3 manage.py makemigrations
37+
38+
migrate:
39+
docker-compose run --rm web python3 manage.py migrate
40+
41+
shell_plus:
42+
docker-compose run --rm web python3 manage.py shell_plus
43+
44+
.PHONY: help start stop ps clean test dockershell shell_plus only_test pep8

README.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ Decenas de personas han colaborado de [diversas maneras](https://github.com/PyAr
1111

1212
## ¿Cómo arranco / instalo el proyecto en mi máquina?
1313

14-
### Vía virtualenv (recomendado)
14+
### Vía virtualenv:
1515

1616
Si querés podés instalar todo el entorno en tu propia maquina, podés ver
1717
instrucciones generales en [esta página de la wiki](https://github.com/PyAr/pyarweb/wiki/Instalaci%C3%B3n-manual)
1818

19-
### Via [Docker](http://docker.com) (No soportada por el momento):
19+
### Via [Docker](http://docker.com):
2020

21-
Estamos trabajando para soportar docker, mientras tanto podés ver las
22-
instrucciones en [esta página de la wiki](https://github.com/PyAr/pyarweb/wiki/Instalacion-con-Docker)
21+
podés ver las instrucciones en [esta página de la wiki](https://github.com/PyAr/pyarweb/wiki/Instalacion-con-Docker)
2322

2423

2524
## Más info

community/templates/community/index.html

+33-52
Original file line numberDiff line numberDiff line change
@@ -60,59 +60,40 @@ <h3 class="text-center"><a href="/wiki/Proyectos">Proyectos de la comunidad</a><
6060
</div>
6161
</section>
6262

63-
<div class="row" style="margin-top: 20px;">
64-
<div class="col-md-12">
65-
66-
<div class="panel panel-default panel-primary">
67-
<div class="panel-heading"><strong><a class="white" href="{% url 'news_list_all' %}">Últimas noticias</a></strong>
68-
<div class="pull-right">
69-
<span class="badge">
70-
<a href="{% url 'news_feed' %}">
71-
<i class="fa fa-rss"></i> RSS
72-
</a>
73-
</span>
74-
</div>
75-
</div>
76-
<div class="panel-body">
77-
{% for article in news %}
78-
<article class="list-group-item">
79-
<time class="published" datetime="{{ article.created.isoformat }}" itemprop="datePublished" title="{{ "Fecha de publicación" }}">{{ article.created|date:"d/m/Y" }}</time>
80-
<h4 class="list-group-item-heading"><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></h4>
81-
<p class="list-group-item-text">{{ article.introduction|default:article.body|html2text|truncatewords:30 }}</p>
82-
</article>
83-
{% endfor %}
84-
</div>
85-
</div>
86-
</div>
87-
88-
<div class="col-md-12">
89-
90-
<div class="panel panel-default panel-primary">
91-
<div class="panel-heading"><strong><a class="white" href="{% url 'jobs_list_all' %}">Últimos avisos de trabajo publicados</a></strong>
92-
93-
<div class="pull-right">
94-
<span class="badge">
95-
<a href="{% url 'jobs_feed' %}">
96-
<i class="fa fa-rss"></i> RSS
97-
</a>
98-
</span>
99-
</div>
100-
101-
102-
</div>
103-
<div class="panel-body">
104-
{% for job in jobs %}
105-
<article class="list-group-item">
106-
<time class="published" datetime="{{ job.created.isoformat }}" itemprop="datePublished" title="{{ "Fecha de publicación" }}">{{ job.created|date:"d/m/Y" }}</time>
107-
<h4 class="list-group-item-heading"><a href="{{ job.get_absolute_url }}">{{ job.title }}</a></h4>
108-
<p class="list-group-item-text">{{ job.description|html2text|truncatewords:30 }}</p>
109-
</article>
110-
{% endfor %}
111-
</div>
63+
<section>
64+
<div class="row" style="margin-top: 20px;">
65+
<div class="col-md-12">
66+
<div class="panel panel-default panel-primary">
67+
<div class="panel-heading">
68+
<strong>Novedades</strong>
69+
</div>
70+
<div class="panel-body">
71+
{% for article in recent %}
72+
<article class="list-group-item">
73+
<time
74+
class="published"
75+
datetime="{{ article.created.isoformat }}"
76+
itemprop="datePublished"
77+
title="{{ "Fecha de publicación" }}"
78+
>
79+
{{ article.created|date:"d/m/Y" }}
80+
</time>
81+
<small class="text-muted">
82+
- en {{ article.category }}
83+
</small>
84+
<h4 class="list-group-item-heading">
85+
<a href="{{ article.get_absolute_url }}">{{ article.title }}</a>
86+
</h4>
87+
<p class="list-group-item-text">
88+
{{ article.description|html2text|truncatewords:30 }}
89+
</p>
90+
</article>
91+
{% endfor %}
92+
</div>
93+
</div>
94+
</div>
11295
</div>
113-
114-
</div>
115-
</div>
96+
</section>
11697

11798

11899
{# IMPLEMENTAR #}

community/tests/__init__.py

Whitespace-only changes.

community/tests/test_homepage.py

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Tests for the community.views.HomePageView class
3+
4+
"""
5+
from django.test import TestCase
6+
7+
from community.views import HomePageView, RECENT_ITEMS_LEN
8+
from events.tests.factories import EventFactory
9+
from jobs.tests.factories import JobFactory
10+
from news.tests.factories import NewsArticleFactory
11+
12+
13+
class GetContextDataRecentKeyTests(TestCase):
14+
def setUp(self):
15+
# shortcut
16+
self.get_context_data = HomePageView().get_context_data
17+
18+
def test_a_recent_key_is_added_to_the_return_value(self):
19+
self.assertIn('recent', self.get_context_data())
20+
21+
def test_events_are_included_in_recent(self):
22+
event = EventFactory()
23+
self.assertEqual([event], self.get_context_data()['recent'])
24+
25+
def test_included_events_have_correct_fields(self):
26+
# Correct fields include 'category', 'created', 'title' and 'description'
27+
EventFactory()
28+
event = self.get_context_data()['recent'][0]
29+
self.assertEqual(event.category, 'Eventos')
30+
self.assertEqual(event.title, event.name)
31+
self.assertEqual(event.created, event.start_at)
32+
# Events already have a description field
33+
34+
def test_jobs_are_included_in_recent(self):
35+
job = JobFactory()
36+
self.assertEqual([job], self.get_context_data()['recent'])
37+
38+
def test_included_jobs_have_correct_fields(self):
39+
JobFactory()
40+
job = self.get_context_data()['recent'][0]
41+
self.assertEqual(job.category, 'Trabajos')
42+
# jobs already have 'created', 'title' and 'description' fields
43+
44+
def test_news_are_included_in_recent(self):
45+
article = NewsArticleFactory()
46+
self.assertEqual([article], self.get_context_data()['recent'])
47+
48+
def test_included_news_have_correct_fields(self):
49+
# Correct fields include 'category', 'created', 'title' and 'description'
50+
NewsArticleFactory()
51+
article = self.get_context_data()['recent'][0]
52+
self.assertEqual(article.category, 'Noticias')
53+
self.assertEqual(article.description, article.body)
54+
# NewsArticle already have a created and title fields
55+
56+
# Independent of the Model type, all list items are sorted by their 'created' field
57+
def test_items_are_sorted_by_the_created_field(self):
58+
job = JobFactory(set_created='1985-10-26 09:00Z') # Middle-age ;-)
59+
event = EventFactory(start_at='1955-11-12 06:38Z') # Oldest
60+
article = NewsArticleFactory(set_created='2015-10-21 09:00Z') # Most recent
61+
# Assert the models are in chronological order
62+
self.assertListEqual([article, job, event], self.get_context_data()['recent'])
63+
64+
def test_recent_is_a_list_with_at_most_10_items(self):
65+
# Create more than RECENT_ITEMS_LEN models and assert that only 10 are kept as recent
66+
for i in range(RECENT_ITEMS_LEN):
67+
JobFactory()
68+
EventFactory()
69+
NewsArticleFactory()
70+
# The loop above creates RECENT_ITEMS_LEN * 3 items
71+
self.assertEqual(len(self.get_context_data()['recent']), RECENT_ITEMS_LEN)

community/views.py

+53-6
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,68 @@
33

44
"""Handle the Views of the Homepage and others."""
55

6-
6+
from django.db.models import F, Value, CharField
77
from django.http import Http404
88
from django.shortcuts import render
9+
from django.views.generic.base import TemplateView
910
from django.views.generic.detail import SingleObjectMixin
1011
from django.views.generic.list import MultipleObjectMixin
1112
from django.utils.translation import ugettext_lazy as _
13+
from django.utils.timezone import now
14+
from events.models import Event
1215
from jobs.models import Job
1316
from news.models import NewsArticle
1417

18+
RECENT_ITEMS_LEN = 10
19+
20+
21+
# Auxiliary function for the homepage context
22+
def aux_qs_to_list_for_context(qs):
23+
"""Cast the given QuerySet to a list with at most RECENT_ITEMS_LEN elements"""
24+
return list(qs[:RECENT_ITEMS_LEN])
25+
26+
27+
class HomePageView(TemplateView):
28+
template_name = "community/index.html"
29+
30+
def get_events_for_context(self):
31+
"""Ensure events have 'category', created' and 'title' fields"""
32+
events = Event.objects.filter(start_at__lt=now())
33+
events = events.order_by('-start_at')
34+
events = events.annotate(
35+
created=F('start_at'),
36+
title=F('name'),
37+
category=Value('Eventos', output_field=CharField()))
38+
return aux_qs_to_list_for_context(events)
39+
40+
def get_jobs_for_context(self):
41+
"""Ensure jobs have a 'category' field"""
42+
jobs = Job.objects.order_by('-created')
43+
jobs = jobs.annotate(category=Value('Trabajos', output_field=CharField()))
44+
return aux_qs_to_list_for_context(jobs)
45+
46+
def get_news_for_context(self):
47+
"""Ensure news have 'category' and 'description' fields"""
48+
news = NewsArticle.objects.order_by('-created')
49+
news = news.annotate(
50+
description=F('body'),
51+
category=Value('Noticias', output_field=CharField()))
52+
return aux_qs_to_list_for_context(news)
53+
54+
def get_context_data(self, **kwargs):
55+
"""Add to the template context a list of the most recent events, jobs and news"""
56+
news = self.get_news_for_context()
57+
jobs = self.get_jobs_for_context()
58+
events = self.get_events_for_context()
59+
# Sort the last news, jobs and events to define the definitive 'recent' list
60+
recent = sorted(news + jobs + events, key=lambda r: r.created, reverse=True)
61+
62+
context = super(HomePageView, self).get_context_data(**kwargs)
63+
context['recent'] = recent[:RECENT_ITEMS_LEN]
64+
return context
65+
1566

16-
def homepage(request):
17-
news = NewsArticle.objects.order_by('-created')[:3]
18-
jobs = Job.objects.order_by('-created')[:3]
19-
return render(request, 'community/index.html',
20-
{'news': news, 'jobs': jobs})
67+
homepage = HomePageView.as_view()
2168

2269

2370
def learning(request):

dev_requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
-r requirements.txt
22
factory-boy==2.8.1
33
ipython==5.3.0
4-
ipdb==0.10.2
4+
ipdb==0.10.2
5+
flake8==3.5.0

docker-compose.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ services:
1515
- POSTGRES_PASSWORD=secret
1616

1717
web:
18-
build: .
18+
image: pyar/pyarweb:dev
1919
command: python3 manage.py runserver 0.0.0.0:8000
2020
volumes:
2121
- .:/code

0 commit comments

Comments
 (0)