diff --git a/blog/tests.py b/blog/tests.py index a1dfee4..b878aed 100644 --- a/blog/tests.py +++ b/blog/tests.py @@ -1,6 +1,7 @@ -from django.test import TestCase, Client +from django.test import TestCase, Client, override_settings from django.core.urlresolvers import reverse from django.contrib.auth.models import User +from django.conf import settings from .models import Post @@ -32,3 +33,59 @@ def test_invalid_detail(self): response = self.client.get( reverse('blog:detail', args=['test-test'])) self.assertEqual(response.status_code, 404) + + def test_pagination(self): + for i in range(settings.BLOG['LIMIT'] + 1): + dummy_data = self.dummy_data + dummy_data['slug'] = dummy_data['slug'] + str(i) + Post.objects.create(author=self.user, **dummy_data) + response = self.client.get(reverse('blog:home')) + self.assertContains(response, "Daha fazla") + + @override_settings(BLOG={ + 'TITLE': 'Test Title', + 'DESCRIPTION': 'Python istanbul Test DESCRIPTION', + 'LIMIT': 5, + 'URL': 'http://pyistanbul.org/', + 'DISQUS_USERNAME': 'helevele', + 'USE_DISQUS': True, + }) + def test_blog_title(self): + response = self.client.get(reverse('blog:home')) + self.assertContains(response, "Test Title") + + @override_settings(BLOG={ + 'TITLE': 'Python istanbul', + 'DESCRIPTION': 'Python istanbul Test DESCRIPTION', + 'LIMIT': 5, + 'URL': 'http://pyistanbul.org/', + 'DISQUS_USERNAME': 'helevele', + 'USE_DISQUS': True, + }) + def test_blog_description(self): + response = self.client.get(reverse('blog:home')) + self.assertContains(response, "Python istanbul Test DESCRIPTION") + + @override_settings(BLOG={ + 'TITLE': 'Python istanbul', + 'DESCRIPTION': 'ython istanbul Gunlugu', + 'LIMIT': 5, + 'URL': 'http://pyistanbul.org/', + 'DISQUS_USERNAME': 'pyistanbul', + 'USE_DISQUS': True, + }) + def test_use_disqus(self): + response = self.client.get(self.post.get_absolute_url()) + self.assertContains(response, "http://disqus.com") + + @override_settings(BLOG={ + 'TITLE': 'Python istanbul', + 'DESCRIPTION': 'Python istanbul Gunlugu', + 'LIMIT': 5, + 'URL': 'http://pyistanbul.org/', + 'DISQUS_USERNAME': 'helevele', + 'USE_DISQUS': True, + }) + def test_disqus_username(self): + response = self.client.get(self.post.get_absolute_url()) + self.assertContains(response, "helevele") diff --git a/conf/requirements.txt b/conf/requirements.txt index 95f4fda..21b2f06 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -5,3 +5,4 @@ django-markitup==2.2.2 django-nose==1.3 gunicorn==19.3 djangospam==1.1.3 +django-allauth==0.19.1 diff --git a/people/admin.py b/people/admin.py index 0e3daf4..8ce8dc0 100644 --- a/people/admin.py +++ b/people/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin -from .models import Person +from .models import Person, SocialAccountLink admin.site.register(Person) +admin.site.register(SocialAccountLink) diff --git a/people/forms.py b/people/forms.py deleted file mode 100644 index 6377d7f..0000000 --- a/people/forms.py +++ /dev/null @@ -1,10 +0,0 @@ -from django import forms - -from .models import Person - - -class PersonForm(forms.ModelForm): - class Meta: - model = Person - fields = ("name", "email", "blog_link", "twitter_username", - "github_username") diff --git a/people/migrations/0003_auto_20150508_2347.py b/people/migrations/0003_auto_20150508_2347.py new file mode 100644 index 0000000..369fde4 --- /dev/null +++ b/people/migrations/0003_auto_20150508_2347.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('people', '0002_auto_20150311_1220'), + ] + + operations = [ + migrations.CreateModel( + name='SocialAccountLink', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('account_type', models.CharField(max_length=10, choices=[(b'twitter', b'Twitter'), (b'home', b'Blog'), (b'github', b'Github')])), + ('link', models.URLField(max_length=255)), + ('user', models.ForeignKey(related_name='links', to=settings.AUTH_USER_MODEL)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.AlterUniqueTogether( + name='socialaccountlink', + unique_together=set([('account_type', 'user')]), + ), + ] diff --git a/people/models.py b/people/models.py index 4fe58da..442725f 100644 --- a/people/models.py +++ b/people/models.py @@ -37,3 +37,26 @@ def __str__(self): def badge(self): if codecs.encode(self.email, "rot13") == "uhfrlvanyo@tznvy.pbz": return "huseyinalbing" + + +@python_2_unicode_compatible +class SocialAccountLink(models.Model): + TWITTER = 'twitter' + BLOG = 'home' + GITHUB = 'github' + + ACCOUNT_TYPE_CHOICES = ( + (TWITTER, 'Twitter'), + (BLOG, 'Blog'), + (GITHUB, 'Github') + ) + account_type = models.CharField(choices=ACCOUNT_TYPE_CHOICES, + max_length=10) + link = models.URLField(max_length=255) + user = models.ForeignKey('auth.User', related_name='links') + + def __str__(self): + return self.get_account_type_display() + + class Meta: + unique_together = ('account_type', 'user',) diff --git a/people/tests.py b/people/tests.py index 9807dcb..5e98bca 100644 --- a/people/tests.py +++ b/people/tests.py @@ -1,3 +1,4 @@ +# coding: utf-8 from django.core.urlresolvers import reverse from django.test import TestCase, Client from django.contrib.auth.models import User @@ -20,17 +21,6 @@ def setUp(self): self.tester = User.objects.create(username='tester') self.client = Client() - def test_create(self): - response = self.client.post(reverse('people:new'), self.person) - self.assertRedirects(response, reverse('people:index')) - self.assertTrue(Person.objects.exists()) - person = Person.objects.get() - self.assertEqual(person.name, 'edi budu') - self.assertEqual(person.email, 'edi@budu.com') - self.assertEqual(person.blog_link, 'http://edibudu.com/') - self.assertEqual(person.twitter_username, 'edibudu') - self.assertEqual(person.github_username, 'edicat') - def test_listing(self): Person.objects.create(**self.person) response = self.client.get(reverse('people:index')) @@ -42,3 +32,36 @@ def test_active_listing(self): Person.objects.create(**person) response = self.client.get(reverse('people:index')) self.assertNotContains(response, "edi budu") + + def test_people_detail(self): + response = self.client.get( + reverse('people:detail', args=[self.tester.username])) + self.assertEqual(response.status_code, 200) + self.assertContains(response, self.tester.username) + + def test_people_detail_passive_user(self): + self.tester.is_active = False + self.tester.save() + response = self.client.get( + reverse('people:detail', args=[self.tester.username])) + self.assertEqual(response.status_code, 404) + + def test_people_detail_not_found(self): + response = self.client.get( + reverse('people:detail', args=["test123"])) + self.assertEqual(response.status_code, 404) + + def test_people_detail_method_not_allowed(self): + response = self.client.post( + reverse('people:detail', args=[self.tester.username])) + self.assertEqual(response.status_code, 405) + + def test_people_detail_password_change_link(self): + self.tester.set_password('123456') + self.tester.save() + self.client.login(username=self.tester.username, password='123456') + response = self.client.get( + reverse('people:detail', args=[self.tester.username])) + self.assertEqual(response.status_code, 200) + self.assertContains(response, self.tester.username) + self.assertContains(response, u"Parola Değiştir") diff --git a/people/urls.py b/people/urls.py index e4f68e3..ad695ea 100644 --- a/people/urls.py +++ b/people/urls.py @@ -1,10 +1,9 @@ -from django.conf.urls import patterns, include, url +from django.conf.urls import url -from .views import PeopleView, CreatePeopleView +from .views import PeopleListView, PeopleDetailView -urlpatterns = patterns( - '', - url(r'^$', PeopleView.as_view(), name='index'), - url(r'^new$', CreatePeopleView.as_view(), name='new'), -) +urlpatterns = [ + url(r'^$', PeopleListView.as_view(), name='index'), + url(r'^(?P[-\w]+)/$', PeopleDetailView.as_view(), name='detail'), +] diff --git a/people/views.py b/people/views.py index f6c263b..27a5e0f 100644 --- a/people/views.py +++ b/people/views.py @@ -1,25 +1,16 @@ # coding: utf-8 +from django.views.generic import ListView, DetailView +from django.contrib.auth.models import User -from django.contrib import messages -from django.core.urlresolvers import reverse -from django.views.generic import ListView, CreateView +from .models import Person -from people.models import Person -from people.forms import PersonForm - -class PeopleView(ListView): +class PeopleListView(ListView): queryset = Person.objects.active() -class CreatePeopleView(CreateView): - model = Person - form_class = PersonForm - success_message = 'Kişi başarıyla eklendi.' - - def form_valid(self, form): - messages.success(self.request, self.success_message) - return super(CreatePeopleView, self).form_valid(form) - - def get_success_url(self): - return reverse("people:index") +class PeopleDetailView(DetailView): + template_name = "people/person_detail.html" + queryset = User.objects.filter(is_active=True) + slug_field = "username" + slug_url_kwarg = "username" diff --git a/presentations/migrations/0002_presentation_user.py b/presentations/migrations/0002_presentation_user.py new file mode 100644 index 0000000..6106098 --- /dev/null +++ b/presentations/migrations/0002_presentation_user.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('presentations', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='presentation', + name='user', + field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True), + preserve_default=True, + ), + ] diff --git a/presentations/migrations/0003_auto_20150507_2301.py b/presentations/migrations/0003_auto_20150507_2301.py new file mode 100644 index 0000000..069adb8 --- /dev/null +++ b/presentations/migrations/0003_auto_20150507_2301.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('presentations', '0002_presentation_user'), + ] + + operations = [ + migrations.AlterField( + model_name='presentation', + name='user', + field=models.ForeignKey(related_name='presentations', blank=True, to=settings.AUTH_USER_MODEL, null=True), + preserve_default=True, + ), + ] diff --git a/presentations/models.py b/presentations/models.py index 02b13a3..6a8f3ac 100644 --- a/presentations/models.py +++ b/presentations/models.py @@ -9,6 +9,8 @@ class Presentation(models.Model): date = models.DateField() link = models.URLField() description = models.TextField(blank=True) + user = models.ForeignKey('auth.User', null=True, blank=True, + related_name='presentations') class Meta: ordering = ['-date'] diff --git a/presentations/tests.py b/presentations/tests.py index fddbc86..295243e 100644 --- a/presentations/tests.py +++ b/presentations/tests.py @@ -5,7 +5,7 @@ from .models import Presentation -class PeopleTest(TestCase): +class PresentationTest(TestCase): presentation = { 'title': 'foo bar', diff --git a/pyist/settings.py b/pyist/settings.py index 7e971af..6770542 100644 --- a/pyist/settings.py +++ b/pyist/settings.py @@ -2,6 +2,8 @@ import os +from django.core.urlresolvers import reverse_lazy + PROJECT_PATH = os.path.abspath(os.getcwd()) DEBUG = False @@ -65,6 +67,8 @@ 'django.core.context_processors.request', 'django.contrib.messages.context_processors.messages', 'blog.context_processors.export_blog_settings', + 'allauth.account.context_processors.account', + 'allauth.socialaccount.context_processors.socialaccount', ) ROOT_URLCONF = 'pyist.urls' @@ -76,7 +80,7 @@ os.path.join(PROJECT_PATH, 'templates'), ) -INSTALLED_APPS = ( +DJANGO_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', @@ -86,17 +90,32 @@ 'django.contrib.admin', 'django.contrib.flatpages', 'django.contrib.sitemaps', +) +THIRD_PARTY_APPS = ( 'django_gravatar', 'markitup', 'nose', + 'allauth', + 'allauth.account', + 'allauth.socialaccount', + 'allauth.socialaccount.providers.github', +) +LOCAL_APPS = ( 'jobs', 'people', 'presentations', 'blog', ) +INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS + THIRD_PARTY_APPS + +AUTHENTICATION_BACKENDS = ( + 'django.contrib.auth.backends.ModelBackend', + 'allauth.account.auth_backends.AuthenticationBackend', +) + LOGGING = { 'version': 1, 'disable_existing_loggers': False, @@ -154,3 +173,13 @@ # Nose Settings TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' + +# auth +LOGIN_REDIRECT_URL = reverse_lazy('blog:home') + +# allauth settings +ACCOUNT_EMAIL_REQUIRED = True +ACCOUNT_EMAIL_VERIFICATION = 'none' +ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = False +SOCIALACCOUNT_EMAIL_VERIFICATION = 'none' +ACCOUNT_LOGOUT_REDIRECT_URL = reverse_lazy('account_login') diff --git a/pyist/urls.py b/pyist/urls.py index 59deb17..96a6513 100644 --- a/pyist/urls.py +++ b/pyist/urls.py @@ -22,6 +22,7 @@ # third party apps url(r'^comments/', include('djangospam.cookie.urls')), + url(r'^accounts/', include('allauth.urls')), # admin url(r'^admin/', include(admin.site.urls)), diff --git a/templates/account/login.html b/templates/account/login.html new file mode 100644 index 0000000..babddd7 --- /dev/null +++ b/templates/account/login.html @@ -0,0 +1,27 @@ +{% extends "account/base.html" %} + +{% load socialaccount %} + +{% block title %}{{ block.super }} - Giriş Yap{% endblock %} + +{% block content %} + +

Giriş Yap

+ +

+ + Github hesabınız ile giriş yapabilirsiniz + veya üye olabilirsiniz. +

+ +
+ {% csrf_token %} + {{ form.as_p }} + {% if redirect_field_value %} + + {% endif %} + + Parolanızı mı unuttunuz? +
+ +{% endblock %} \ No newline at end of file diff --git a/templates/account/logout.html b/templates/account/logout.html new file mode 100644 index 0000000..3ba85e9 --- /dev/null +++ b/templates/account/logout.html @@ -0,0 +1,18 @@ +{% extends "account/base.html" %} + + +{% block title %}{{ block.super }} - Çıkış Yap{% endblock %} + +{% block content %} +

Çıkış Yap

+ +

Çıkış yapmak istediğine emin misin ?

+ +
+ {% csrf_token %} + {% if redirect_field_value %} + + {% endif %} + +
+{% endblock %} \ No newline at end of file diff --git a/templates/account/password_change.html b/templates/account/password_change.html new file mode 100644 index 0000000..ccf31b7 --- /dev/null +++ b/templates/account/password_change.html @@ -0,0 +1,13 @@ +{% extends "account/base.html" %} + +{% block title %}{{ block.super }} - Parola Değiştir{% endblock %} + +{% block content %} +

Parola Değiştir

+ +
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} \ No newline at end of file diff --git a/templates/account/password_reset.html b/templates/account/password_reset.html new file mode 100644 index 0000000..3d48fbc --- /dev/null +++ b/templates/account/password_reset.html @@ -0,0 +1,23 @@ +{% extends "account/base.html" %} + +{% load account %} + +{% block title %}{{ block.super }} - Parola Sıfırlama{% endblock %} + +{% block content %} + +

Parola Sıfırlama

+ {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} + +

Parolanızı mı unuttunuz? E-posta adresinizi aşağıya yazın, size parolanızı sıfırlamanıza imkan veren e-postayı göndereceğiz.

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

Parolanızı sıfırlarken herhangi bir sorunla karşılaşırsanız lütfen bize ulaşın.

+{% endblock %} \ No newline at end of file diff --git a/templates/account/signup.html b/templates/account/signup.html new file mode 100644 index 0000000..057f04d --- /dev/null +++ b/templates/account/signup.html @@ -0,0 +1,20 @@ +{% extends "account/base.html" %} + +{% block title %}{{ block.super }} - Üye Ol{% endblock %} + +{% block content %} +

Üye Ol

+

+ Zaten hesabınız var mı? O zaman lütfen + giriş yapın. +

+ +
+ {% csrf_token %} + {{ form.as_p }} + {% if redirect_field_value %} + + {% endif %} + +
+{% endblock %} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 46d7b92..a70465e 100644 --- a/templates/index.html +++ b/templates/index.html @@ -31,10 +31,27 @@

Nasıl iletişim kurabilirim?

Her gün Freenode'daki #pyistanbul kanalında buluşuyoruz.

Desteğe ihtiyacım var

IRC'de ya da python-istanbul e-posta listesinde sorularınızı sorabilirsiniz.

-

Listeye Kaydol

+

+ {% if not user.is_authenticated %} + + Kayıt Ol + + + Giriş Yap + + {% else %} + + Profilim + + + Çıkış Yap + + {% endif %} +

- O'Reilly User Groups + + O'Reilly User Groups +

{% endblock %} diff --git a/templates/people/person_detail.html b/templates/people/person_detail.html new file mode 100644 index 0000000..22d276b --- /dev/null +++ b/templates/people/person_detail.html @@ -0,0 +1,52 @@ +{% extends "base.html" %} + +{% load gravatar %} +{% load people_extras %} + +{% block title %}{{ block.super }} - {{ object.username }}{% endblock %} + +{% block content %} +
+ {% gravatar object.email 220 %} + + {% if object.links.count > 0 %} +
+ {% for link in object.links.all %} + + {% fontawesome link.account_type '2x' %} + + {% endfor %} +
+ {% endif %} + + {% if user.is_authenticated and user.username == object.username %} + + Parola Değiştir + + {% endif %} +
+
+ {% if object.get_full_name %} + {{ object.get_full_name }} + {% endif %} + + + @{{ object.username }} + + + {% if object.presentations.count > 0 %} +
+ +
+ {% endif %} + +
+{% endblock content %} \ No newline at end of file diff --git a/templates/people/person_form.html b/templates/people/person_form.html deleted file mode 100644 index ed95472..0000000 --- a/templates/people/person_form.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -

Yeni kişi

- {% include 'djangospam/cookieform.html' %} -
- {% csrf_token %} - {% for field in form %} -
- {{ field.errors }} - {{ field.label_tag }} -
- {{ field }} -

{{ field.help_text }}

-
-
- {% endfor %} -
- -
-
- -{% endblock %} diff --git a/templates/people/person_list.html b/templates/people/person_list.html index 49e6e3e..6935926 100644 --- a/templates/people/person_list.html +++ b/templates/people/person_list.html @@ -3,11 +3,10 @@ {% load gravatar %} {% load people_extras %} -{% block content %} +{% block title %}{{ block.super }} - İnsanlar{% endblock %} -
- Yeni Kişi Ekle -
+{% block content %} +

İnsanlar