├── .gitignore ├── LICENSE ├── README.md ├── manage.py ├── places ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20160816_1718.py │ ├── 0003_auto_20160818_0833.py │ └── __init__.py ├── models.py ├── tests.py └── views.py ├── profiles ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py └── views.py ├── static └── style.css ├── templates ├── base.html ├── index.html ├── login.html ├── new_media.html ├── new_place.html ├── new_review.html ├── place.html └── register.html └── velespi ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | 91 | 92 | db.sqlite3 93 | uploads/ 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 lyk2016-python 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # velespi 2 | Bisikletçiler ve Bisiklet Dostu İşletmeler Ağı 3 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "velespi.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /places/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyk2016-python/velespi/c327efcde52da556663c075e414d854f5a3b131c/places/__init__.py -------------------------------------------------------------------------------- /places/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from places.models import ( 4 | Place, Category, Review, Media 5 | ) 6 | 7 | class MediaInline(admin.TabularInline): 8 | model = Media 9 | extra = 0 10 | 11 | class ReviewInline(admin.TabularInline): 12 | model = Review 13 | extra = 0 14 | 15 | class PlaceAdmin(admin.ModelAdmin): 16 | list_display = ('name', 'user', 'category', 'has_wifi', 17 | 'review_count') 18 | list_editable = ('category', 'has_wifi') 19 | actions = ('set_wifi_true', ) 20 | search_fields = ('name', 'user__username') 21 | inlines = [ 22 | MediaInline, 23 | ReviewInline, 24 | ] 25 | 26 | def set_wifi_true(self, request, queryset): 27 | queryset.update(has_wifi=True) 28 | set_wifi_true.short_description = 'Mahmut' 29 | 30 | admin.site.register(Place, PlaceAdmin) 31 | admin.site.register(Category) 32 | admin.site.register(Review) 33 | admin.site.register(Media) 34 | -------------------------------------------------------------------------------- /places/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PlacesConfig(AppConfig): 5 | name = 'places' 6 | -------------------------------------------------------------------------------- /places/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms import ( 2 | ModelForm, HiddenInput, ValidationError 3 | ) 4 | 5 | from places.models import Place, Media, Review 6 | 7 | class PlaceCreationForm(ModelForm): 8 | class Meta: 9 | model = Place 10 | fields = ( 11 | 'name', 12 | 'coordinates', 13 | 'category', 14 | 'has_wifi', 15 | 'telephone', 16 | 'description', 17 | ) 18 | widgets = { 19 | 'coordinates': HiddenInput 20 | } 21 | 22 | def clean_coordinates(self): 23 | coords = self.cleaned_data['coordinates'] 24 | 25 | try: 26 | lat, lng = coords.split(',') 27 | lat = float(lat) 28 | lng = float(lng) 29 | 30 | if ( 31 | lat < -90 or lat > 90 or 32 | lng < -180 or lng > 180 33 | ): 34 | raise ValidationError('Geçerli bir koordinat girin.') 35 | 36 | except ValueError: 37 | raise ValidationError('Koordinat girin.') 38 | 39 | return coords 40 | 41 | 42 | class MediaCreationForm(ModelForm): 43 | class Meta: 44 | model = Media 45 | fields = ('image', ) 46 | 47 | 48 | class ReviewCreationForm(ModelForm): 49 | class Meta: 50 | model = Review 51 | fields = ('comment', 'vote') 52 | -------------------------------------------------------------------------------- /places/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10 on 2016-08-15 11:48 3 | from __future__ import unicode_literals 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | initial = True 13 | 14 | dependencies = [ 15 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 16 | ] 17 | 18 | operations = [ 19 | migrations.CreateModel( 20 | name='Category', 21 | fields=[ 22 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 23 | ('name', models.CharField(max_length=255)), 24 | ], 25 | ), 26 | migrations.CreateModel( 27 | name='Media', 28 | fields=[ 29 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 30 | ('image', models.ImageField(upload_to='uploads')), 31 | ], 32 | ), 33 | migrations.CreateModel( 34 | name='Place', 35 | fields=[ 36 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 37 | ('name', models.CharField(max_length=255)), 38 | ('is_active', models.BooleanField(default=False)), 39 | ('coordinates', models.CharField(blank=True, max_length=255, null=True)), 40 | ('has_wifi', models.BooleanField(default=False)), 41 | ('telephone', models.CharField(blank=True, max_length=255, null=True)), 42 | ('description', models.TextField(blank=True, null=True)), 43 | ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='places.Category')), 44 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 45 | ], 46 | ), 47 | migrations.CreateModel( 48 | name='Review', 49 | fields=[ 50 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 51 | ('comment', models.TextField(blank=True, null=True)), 52 | ('vote', models.IntegerField(default=3)), 53 | ('place', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='places.Place')), 54 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 55 | ], 56 | ), 57 | migrations.AddField( 58 | model_name='media', 59 | name='place', 60 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='places.Place'), 61 | ), 62 | ] 63 | -------------------------------------------------------------------------------- /places/migrations/0002_auto_20160816_1718.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10 on 2016-08-16 17:18 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('places', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterModelOptions( 16 | name='category', 17 | options={'verbose_name_plural': 'Categories'}, 18 | ), 19 | migrations.AlterModelOptions( 20 | name='media', 21 | options={'verbose_name_plural': 'Media'}, 22 | ), 23 | migrations.AlterField( 24 | model_name='media', 25 | name='image', 26 | field=models.ImageField(upload_to='places'), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /places/migrations/0003_auto_20160818_0833.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.10 on 2016-08-18 08:33 3 | from __future__ import unicode_literals 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('places', '0002_auto_20160816_1718'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='place', 20 | name='likes', 21 | field=models.ManyToManyField(blank=True, related_name='liked_places', to=settings.AUTH_USER_MODEL), 22 | ), 23 | migrations.AlterField( 24 | model_name='place', 25 | name='coordinates', 26 | field=models.CharField(max_length=255, null=True), 27 | ), 28 | migrations.AlterField( 29 | model_name='place', 30 | name='user', 31 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='added_places', to=settings.AUTH_USER_MODEL), 32 | ), 33 | migrations.AlterField( 34 | model_name='review', 35 | name='vote', 36 | field=models.IntegerField(choices=[(1, 'Berbat'), (2, 'Kötü'), (3, 'Meh'), (4, 'Uh'), (5, 'Yıkılıyor')], default=3), 37 | ), 38 | ] 39 | -------------------------------------------------------------------------------- /places/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyk2016-python/velespi/c327efcde52da556663c075e414d854f5a3b131c/places/migrations/__init__.py -------------------------------------------------------------------------------- /places/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.conf import settings 3 | from django.utils.encoding import smart_text 4 | 5 | 6 | class Category(models.Model): 7 | name = models.CharField(max_length=255) 8 | 9 | class Meta: 10 | verbose_name_plural = "Categories" 11 | 12 | def __str__(self): 13 | return smart_text(self.name) 14 | 15 | class PlaceManager(models.Manager): 16 | def get_queryset(self): 17 | qs = super(PlaceManager, self).get_queryset() 18 | return qs.filter(user__is_active=True) 19 | 20 | def active_places(self): 21 | return self.get_queryset().filter( 22 | is_active=True, 23 | ) 24 | 25 | class Place(models.Model): 26 | user = models.ForeignKey(settings.AUTH_USER_MODEL, 27 | related_name='added_places') 28 | name = models.CharField(max_length=255) 29 | is_active = models.BooleanField(default=False) 30 | coordinates = models.CharField(max_length=255, null=True, blank=False) 31 | category = models.ForeignKey(Category, blank=True, null=True) 32 | has_wifi = models.BooleanField(default=False) 33 | telephone = models.CharField(max_length=255, blank=True, null=True) 34 | description = models.TextField(blank=True, null=True) 35 | likes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, 36 | related_name='liked_places') 37 | 38 | objects = PlaceManager() 39 | all_objects = models.Manager() 40 | 41 | def __str__(self): 42 | return smart_text(self.name) 43 | 44 | @models.permalink 45 | def get_absolute_url(self): 46 | return ('place_detail', (self.id,)) 47 | 48 | def review_count(self): 49 | return self.review_set.count() 50 | 51 | class Review(models.Model): 52 | user = models.ForeignKey(settings.AUTH_USER_MODEL) 53 | place = models.ForeignKey(Place) 54 | comment = models.TextField(null=True, blank=True) 55 | vote = models.IntegerField( 56 | default=3, 57 | choices=( 58 | (1, 'Berbat'), 59 | (2, 'Kötü'), 60 | (3, 'Meh'), 61 | (4, 'Uh'), 62 | (5, 'Yıkılıyor'), 63 | ) 64 | ) 65 | 66 | def __str__(self): 67 | return smart_text(self.comment) 68 | 69 | class Media(models.Model): 70 | place = models.ForeignKey(Place) 71 | image = models.ImageField(upload_to="places") 72 | 73 | class Meta: 74 | verbose_name_plural = "Media" 75 | 76 | def __str__(self): 77 | return smart_text(self.image.url) 78 | -------------------------------------------------------------------------------- /places/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /places/views.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from django.shortcuts import render, get_object_or_404, redirect 4 | from django.contrib import messages 5 | from django.http import HttpResponse 6 | from django.contrib.auth.decorators import login_required 7 | 8 | from places.models import Place 9 | from places.forms import PlaceCreationForm, MediaCreationForm, ReviewCreationForm 10 | 11 | 12 | def index(request): 13 | return render( 14 | request, 15 | 'index.html', 16 | { 17 | 'places': Place.objects.all(), 18 | } 19 | ) 20 | 21 | def detail(request, id): 22 | return render( 23 | request, 24 | 'place.html', 25 | { 26 | 'place': get_object_or_404(Place, id=id), 27 | } 28 | ) 29 | 30 | @login_required(login_url='login') 31 | def new_place(request): 32 | form = PlaceCreationForm() 33 | 34 | if request.method == "POST": 35 | form = PlaceCreationForm(request.POST) 36 | if form.is_valid(): 37 | form.instance.user = request.user 38 | form.save() 39 | messages.info( 40 | request, 41 | 'Tebrikler. Yer bildiriminiz başarıyla alındı. ' 42 | 'Editör onayından geçtikten sonra yayınlanacaktır.' 43 | ) 44 | return redirect('/') 45 | 46 | return render( 47 | request, 48 | 'new_place.html', 49 | { 50 | 'form': form, 51 | } 52 | ) 53 | 54 | @login_required(login_url='login') 55 | def new_media(request, place_id): 56 | place = get_object_or_404(Place, id=place_id) 57 | form = MediaCreationForm() 58 | 59 | if request.method == "POST": 60 | form = MediaCreationForm(request.POST, request.FILES) 61 | if form.is_valid(): 62 | form.instance.place = place 63 | form.save() 64 | return redirect(place.get_absolute_url()) 65 | 66 | return render( 67 | request, 68 | 'new_media.html', 69 | { 70 | 'place': place, 71 | 'form': form, 72 | } 73 | ) 74 | 75 | @login_required(login_url='login') 76 | def new_review(request, place_id): 77 | place = get_object_or_404(Place, id=place_id) 78 | form = ReviewCreationForm() 79 | 80 | if request.method == "POST": 81 | form = ReviewCreationForm(request.POST) 82 | if form.is_valid(): 83 | form.instance.user = request.user 84 | form.instance.place = place 85 | form.save() 86 | return redirect(place.get_absolute_url()) 87 | 88 | return render( 89 | request, 90 | 'new_review.html', 91 | { 92 | 'place': place, 93 | 'form': form, 94 | } 95 | ) 96 | 97 | @login_required(login_url='login') 98 | def like_place(request, place_id): 99 | place = get_object_or_404(Place, id=place_id) 100 | 101 | if request.method == "POST": 102 | 103 | if request.user in place.likes.all(): 104 | place.likes.remove(request.user) 105 | action = 'unlike' 106 | else: 107 | place.likes.add(request.user) 108 | action = 'like' 109 | 110 | if request.is_ajax(): 111 | return HttpResponse( 112 | json.dumps({ 113 | 'count': place.likes.count(), 114 | 'action': action 115 | }) 116 | ) 117 | 118 | else: 119 | return HttpResponse(status_code=403) 120 | 121 | return redirect(place.get_absolute_url()) 122 | -------------------------------------------------------------------------------- /profiles/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyk2016-python/velespi/c327efcde52da556663c075e414d854f5a3b131c/profiles/__init__.py -------------------------------------------------------------------------------- /profiles/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /profiles/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ProfilesConfig(AppConfig): 5 | name = 'profiles' 6 | -------------------------------------------------------------------------------- /profiles/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.forms import UserCreationForm 2 | from django.contrib.auth.models import User 3 | from django.contrib.auth import authenticate 4 | from django.core.exceptions import ValidationError 5 | 6 | from django import forms 7 | 8 | 9 | class RegistrationForm(UserCreationForm): 10 | class Meta: 11 | fields = ['username', 'email'] 12 | model = User 13 | 14 | class LoginForm(forms.Form): 15 | username = forms.CharField(required=True) 16 | password = forms.CharField(widget=forms.PasswordInput, required=True) 17 | 18 | def clean(self): 19 | username = self.cleaned_data.get("username") 20 | password = self.cleaned_data.get("password") 21 | 22 | if not username or not password: 23 | return self.cleaned_data 24 | 25 | user = authenticate(username=username, 26 | password=password) 27 | 28 | if user: 29 | self.user = user 30 | else: 31 | raise ValidationError("Yanlış kullanıcı adı veya şifre!") 32 | 33 | return self.cleaned_data 34 | -------------------------------------------------------------------------------- /profiles/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyk2016-python/velespi/c327efcde52da556663c075e414d854f5a3b131c/profiles/migrations/__init__.py -------------------------------------------------------------------------------- /profiles/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /profiles/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /profiles/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.contrib import messages 3 | from django.contrib.auth import ( 4 | login as auth_login, 5 | logout as auth_logout 6 | ) 7 | 8 | from profiles.forms import RegistrationForm, LoginForm 9 | 10 | def register(request): 11 | form = RegistrationForm() 12 | 13 | if request.method == 'POST': 14 | form = RegistrationForm(request.POST) 15 | 16 | if form.is_valid(): 17 | form.save() 18 | 19 | messages.info( 20 | request, 21 | 'Kayıt başarılı. Şimdi login olabilirsiniz.' 22 | ) 23 | 24 | return redirect('login') 25 | 26 | return render(request, 'register.html', { 27 | 'form': form, 28 | }) 29 | 30 | def login(request): 31 | form = LoginForm() 32 | 33 | if request.method == 'POST': 34 | form = LoginForm(request.POST) 35 | 36 | if form.is_valid(): 37 | auth_login(request, form.user) 38 | messages.info( 39 | request, 40 | 'Giriş yaptınız.' 41 | ) 42 | 43 | return render(request, 'login.html', { 44 | 'form': form 45 | }) 46 | 47 | def logout(request): 48 | auth_logout(request) 49 | return redirect('/') 50 | -------------------------------------------------------------------------------- /static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica; 3 | } 4 | 5 | .container { 6 | width: 600px; 7 | margin: auto; 8 | } 9 | 10 | #logo { 11 | width: 120px; 12 | text-align: center; 13 | float: left; 14 | } 15 | 16 | #logo a { 17 | display: inline-block; 18 | padding: 20px 10px; 19 | color: black; 20 | font-size: 2em; 21 | text-decoration: none; 22 | font-weight: normal; 23 | color: black; 24 | border-radius: 5px; 25 | } 26 | 27 | .header { 28 | margin: 10px 0; 29 | overflow: hidden; 30 | } 31 | 32 | .content { 33 | border-top: 1px solid black; 34 | border-bottom: 1px solid black; 35 | padding: 30px 0; 36 | } 37 | 38 | .footer { 39 | padding: 20px; 40 | } 41 | 42 | #nav { 43 | width: 400px; 44 | margin: 35px auto; 45 | float: right; 46 | text-align: center; 47 | } 48 | 49 | #nav a { 50 | color: black; 51 | margin: 0 10px; 52 | } 53 | 54 | h3 { 55 | margin: 0; 56 | padding: 10px 0; 57 | } 58 | 59 | form label { 60 | display: block; 61 | } 62 | 63 | .helptext { 64 | display: block; 65 | color: gray; 66 | } 67 | 68 | #map { 69 | height: 300px; 70 | } -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | {% block title %}Velespi{% endblock %} 6 | 7 | 8 | 9 | 10 |
11 | {% if messages %} 12 | 17 | {% endif %} 18 |
19 | 22 | 32 |
33 |
34 | {% block content %} 35 | PLACEHOLDER 36 | {% endblock %} 37 |
38 | 41 |
42 | 43 | 44 | 45 | 46 | {% block js %} 47 | {% endblock %} 48 | 49 | 50 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |
6 | 7 | {% endblock %} 8 | 9 | {% block js %} 10 | 34 | 35 | {% endblock %} 36 | -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

Login

5 | 6 |
7 | {% csrf_token %} 8 | {{ form.as_p }} 9 | 10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /templates/new_media.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

{{ place }} için yeni bir fotoğraf:

5 | 6 |
7 | {% csrf_token %} 8 | {{ form.as_p }} 9 | 10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /templates/new_place.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

Yeni Yer Bildirimi

5 |
6 | {% csrf_token %} 7 | {{ form.as_p }} 8 |
9 | 10 |
11 | {% endblock %} 12 | 13 | 14 | {% block js %} 15 | 35 | {% endblock %} -------------------------------------------------------------------------------- /templates/new_review.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

{{ place }} için yeni bir yorum:

5 | 6 |
7 | {% csrf_token %} 8 | {{ form.as_p }} 9 | 10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /templates/place.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |

{{ place.name }}

6 |

7 | {{ place.likes.count }} kişi beğendi. 8 | 9 | {% if user in place.likes.all %} 10 | Beğenmekten vazgeç 11 | {% else %} 12 | Beğen 13 | {% endif %} 14 |

15 |
16 |

17 | {{ place.description|linebreaksbr }} 18 |

19 | {% if place.review_count > 0 %} 20 |

Reviews

21 | {% for review in place.review_set.all %} 22 |
23 | {{ review.comment }} 24 | ({{ review.vote }}) 25 | 26 | {{ review.user.username }} 27 | 28 |
29 | {% endfor %} 30 | {% endif %} 31 | 32 |

Fotoğraflar

33 | {% for media in place.media_set.all %} 34 | 35 | {% empty %} 36 |

37 | Bu yerin hiç fotoğrafı yok. 38 |

39 | {% endfor %} 40 | 41 |

42 | Fotoğraf ekle 43 | Yorum ekle 44 |

45 | 46 | {% endblock %} 47 | 48 | {% block js %} 49 | 83 | {% endblock %} 84 | -------------------------------------------------------------------------------- /templates/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

Register

5 | 6 |
7 | {% csrf_token %} 8 | {{ form.as_p }} 9 | 10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /velespi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyk2016-python/velespi/c327efcde52da556663c075e414d854f5a3b131c/velespi/__init__.py -------------------------------------------------------------------------------- /velespi/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for velespi project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.10. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.10/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '5$h$am*utm$nteg5(jw2+4(s2#u@db7*s$e-#-*&d#mhqi0&80' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 41 | 'places', 42 | 'profiles', 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | 'django.middleware.security.SecurityMiddleware', 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | 'django.contrib.messages.middleware.MessageMiddleware', 52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 53 | ] 54 | 55 | ROOT_URLCONF = 'velespi.urls' 56 | 57 | TEMPLATES = [ 58 | { 59 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 60 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 61 | 'APP_DIRS': True, 62 | 'OPTIONS': { 63 | 'context_processors': [ 64 | 'django.template.context_processors.debug', 65 | 'django.template.context_processors.request', 66 | 'django.contrib.auth.context_processors.auth', 67 | 'django.contrib.messages.context_processors.messages', 68 | ], 69 | }, 70 | }, 71 | ] 72 | 73 | WSGI_APPLICATION = 'velespi.wsgi.application' 74 | 75 | 76 | # Database 77 | # https://docs.djangoproject.com/en/1.10/ref/settings/#databases 78 | 79 | DATABASES = { 80 | 'default': { 81 | 'ENGINE': 'django.db.backends.sqlite3', 82 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 83 | } 84 | } 85 | 86 | 87 | # Password validation 88 | # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators 89 | 90 | if not DEBUG: 91 | AUTH_PASSWORD_VALIDATORS = [ 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 100 | }, 101 | { 102 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 103 | }, 104 | ] 105 | 106 | 107 | # Internationalization 108 | # https://docs.djangoproject.com/en/1.10/topics/i18n/ 109 | 110 | LANGUAGE_CODE = 'tr-TR' 111 | 112 | TIME_ZONE = 'UTC' 113 | 114 | USE_I18N = True 115 | 116 | USE_L10N = True 117 | 118 | USE_TZ = True 119 | 120 | 121 | # Static files (CSS, JavaScript, Images) 122 | # https://docs.djangoproject.com/en/1.10/howto/static-files/ 123 | 124 | STATIC_URL = '/static/' 125 | 126 | MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads') 127 | MEDIA_URL = '/media/' 128 | 129 | 130 | STATICFILES_DIRS = [ 131 | os.path.join(BASE_DIR, 'static') 132 | ] 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /velespi/urls.py: -------------------------------------------------------------------------------- 1 | """velespi URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.10/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf.urls import url 17 | from django.contrib import admin 18 | from django.conf import settings 19 | from django.views.static import serve 20 | from places.views import ( 21 | index, detail, new_place, new_media, new_review, 22 | like_place 23 | ) 24 | from profiles.views import register, login, logout 25 | 26 | urlpatterns = [ 27 | url(r'^admin/', admin.site.urls), 28 | url(r'^$', index), 29 | url(r'^register$', register, name="register"), 30 | url(r'^login$', login, name="login"), 31 | url(r'^logout$', logout, name="logout"), 32 | url(r'^places/(?P\d+)$', detail, name='place_detail'), 33 | url(r'^places/(?P\d+)/new-media$', new_media, name='new_media'), 34 | url(r'^places/(?P\d+)/new-review$', new_review, name='new_review'), 35 | url(r'^places/(?P\d+)/like$', like_place, name='like_place'), 36 | url(r'^new-place$', new_place, name="new_place"), 37 | ] 38 | 39 | if settings.DEBUG: 40 | urlpatterns += [ 41 | url(r'^media/(?P.*)$', serve, { 42 | 'document_root': settings.MEDIA_ROOT, 43 | }), 44 | ] 45 | 46 | 47 | -------------------------------------------------------------------------------- /velespi/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for velespi project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "velespi.settings") 15 | 16 | application = get_wsgi_application() 17 | --------------------------------------------------------------------------------