-
-
Save Flobin/38bbd5fde27904e1ef4d5798eda0ab07 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="article-form"> | |
{% if form.errors %} | |
{% for field in form %} | |
{% for error in field.errors %} | |
<p class="article-form__error"> | |
<strong>{{ error|escape }}</strong> | |
</p> | |
{% endfor %} | |
{% endfor %} | |
{% for error in form.non_field_errors %} | |
<p class="article-form__error"> | |
<strong>{{ error|escape }}</strong> | |
</p> | |
{% endfor %} | |
{% endif %} | |
<form action="{% url 'article-submit' %}" method="POST"> | |
{% csrf_token %} | |
{% for field in form %} | |
<fieldset class="article-form__field"> | |
{% if field.name == "categories"%} | |
{{ field.label_tag }} | |
<ul id={{ field.auto_id }}> | |
{% for checkbox in field %} | |
<li> | |
{{ checkbox.tag }} | |
<label for="{{ checkbox.id_for_label }}"> | |
{{ checkbox.choice_label }} | |
</label> | |
</li> | |
{% endfor %} | |
</ul> | |
{% elif field.name == "city" %} | |
{{ field.label_tag }} | |
<ul id={{ field.auto_id }}> | |
{% for radio in field %} | |
<li> | |
{{ radio.tag }} | |
<label for="{{ radio.id_for_label }}"> | |
{{ radio.choice_label }} | |
</label> | |
</li> | |
{% endfor %} | |
</ul> | |
{% else %} | |
{{ field.label_tag }} {{ field }} | |
{% endif %} | |
</fieldset> | |
{% endfor %} | |
<fieldset class="article-form__field"> | |
<input class="button" type="submit" value="save"> | |
</fieldset> | |
</form> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% extends 'articles/base.html' %} | |
{% block extra_head_stuff %} | |
{{ form.media }} | |
{% endblock extra_head_stuff %} | |
{% block article-submit %} | |
<h2 class="h3">Submit a new article</h2> | |
{% include 'articles/article-submit-form.html' %} | |
{% endblock article-submit %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% load staticfiles %} | |
<!doctype html> | |
<html class="no-js" lang="en-US"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="x-ua-compatible" content="ie=edge"> | |
<title>Togethere</title> | |
<meta name="description" content=""> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
{% block extra_head_stuff %} | |
{% endblock extra_head_stuff %} | |
<script> | |
(function(d) { | |
var config = { | |
kitId: 'snd6kgu', | |
scriptTimeout: 3000, | |
async: true | |
}, | |
h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s) | |
})(document); | |
</script> | |
<link rel="stylesheet" type="text/css" href="{% static 'articles/build/css/main.css' %}" /> | |
</head> | |
<body id="body"> | |
<header class="site-header"> | |
<a href="/"> | |
<img src="{% static 'articles/build/img/togethere-logo.svgz' %}" id="logo" alt="Click this togethere logo to go to the home page" role="img"> | |
</a> | |
<nav role="navigation" class="top-nav"> | |
<div class="top-nav__links"> | |
<a href="{% url 'categories' %}">Categories</a> | |
<a href="{% url 'cities' %}">Cities</a> | |
</div> | |
<div id="auth" class="top-nav__links"> | |
{% load account %} | |
{% if user.is_authenticated %} | |
You are signed in as: {% user_display user %} - | |
<a href="/accounts/logout/">log out</a> | |
{% else %} | |
<a href="/accounts/login/">log in</a> <a href="/accounts/register/">register</a> | |
{% endif %} | |
</div> | |
</nav> | |
</header> | |
<main class="content container"> | |
{% block articles %} | |
{% endblock articles %} | |
{% block article %} | |
{% endblock article %} | |
{% block categories %} | |
{% endblock categories %} | |
{% block category %} | |
{% endblock category %} | |
{% block cities %} | |
{% endblock cities %} | |
{% block city %} | |
{% endblock city %} | |
{% block article-submit %} | |
{% endblock article-submit %} | |
{% block article-update %} | |
{% endblock article-update %} | |
{% block article-delete %} | |
{% endblock article-delete %} | |
{% block profile %} | |
{% endblock profile %} | |
</div> | |
<footer class="site-footer"> | |
</footer> | |
<script src="{% static 'articles/build/lib/node_modules/pjax/pjax.js' %}"></script> | |
<script src="{% static 'articles/build/js/main.js' %}"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static | |
|-src | |
| |-styles | |
| |-scripts | |
| |-images | |
|-build | |
| |-css | |
| |-js | |
| |-img | |
| |-lib | |
| | |-package.json | |
| | |-node_modules | |
| | | |-tinymce | |
| | | | |-tinymce.js | |
| | | | |-more_tinymce_files_here | |
|-node_modules | |
|-gulpfile.js | |
|-package.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django import forms | |
from django.forms import ModelForm | |
from tinymce.widgets import TinyMCE | |
from .models import Article, Category, City | |
TITLE_LENGTH_ERROR = "This title is too long, please make it 200 characters or less." | |
TITLE_EMPTY_ERROR = "You’ll have to add a title." | |
TEXT_EMPTY_ERROR = "Please enter some text." | |
NO_CATEGORY_ERROR = "Please select a category." | |
NO_CITY_ERROR = "Please select a city." | |
class ArticleForm(ModelForm): | |
text = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30})) | |
class Meta: | |
model = Article | |
fields = ['title', 'text', 'categories', 'city'] | |
widgets = {'title': forms.TextInput(attrs={ | |
'placeholder': 'Enter a descriptive title'}), | |
'categories': forms.CheckboxSelectMultiple(choices=Category.CATEGORY_CHOICES), | |
'city': forms.RadioSelect(choices=City.CITY_CHOICES), | |
} | |
error_messages = { | |
'title': { | |
'max_length': TITLE_LENGTH_ERROR, | |
'required': TITLE_EMPTY_ERROR, | |
}, | |
'text': { | |
'required': TEXT_EMPTY_ERROR, | |
}, | |
'categories': { | |
'required': NO_CATEGORY_ERROR, | |
}, | |
'city': { | |
'required': NO_CITY_ERROR, | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Django settings for togethere project. | |
Generated by 'django-admin startproject' using Django 1.9.7. | |
For more information on this file, see | |
https://docs.djangoproject.com/en/1.9/topics/settings/ | |
For the full list of settings and their values, see | |
https://docs.djangoproject.com/en/1.9/ref/settings/ | |
""" | |
import os | |
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) | |
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
# Quick-start development settings - unsuitable for production | |
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ | |
# SECURITY WARNING: keep the secret key used in production secret! | |
SECRET_KEY = 'br&avzw7u$$c+xz&&z#e#$n3(0k4&z_m__#p%xxwc@a5$g*gi3' | |
# SECURITY WARNING: don't run with debug turned on in production! | |
DEBUG = True | |
ALLOWED_HOSTS = [] | |
# Application definition | |
INSTALLED_APPS = [ | |
'django.contrib.admin', | |
'django.contrib.auth', | |
'django.contrib.contenttypes', | |
'django.contrib.sessions', | |
'django.contrib.messages', | |
'django.contrib.staticfiles', | |
'django.contrib.sites', | |
'articles', | |
'allauth', | |
'allauth.account', | |
'allauth.socialaccount', | |
'allauth.socialaccount.providers.facebook', | |
'tinymce', | |
] | |
MIDDLEWARE_CLASSES = [ | |
'django.middleware.security.SecurityMiddleware', | |
'django.contrib.sessions.middleware.SessionMiddleware', | |
'django.middleware.common.CommonMiddleware', | |
'django.middleware.csrf.CsrfViewMiddleware', | |
'django.contrib.auth.middleware.AuthenticationMiddleware', | |
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', | |
'django.contrib.messages.middleware.MessageMiddleware', | |
'django.middleware.clickjacking.XFrameOptionsMiddleware', | |
] | |
ROOT_URLCONF = 'togethere.urls' | |
TEMPLATES = [ | |
{ | |
'BACKEND': 'django.template.backends.django.DjangoTemplates', | |
'DIRS': [], | |
'APP_DIRS': True, | |
'OPTIONS': { | |
'context_processors': [ | |
'django.template.context_processors.debug', | |
'django.template.context_processors.request', | |
'django.contrib.auth.context_processors.auth', | |
'django.contrib.messages.context_processors.messages', | |
], | |
}, | |
}, | |
] | |
AUTHENTICATION_BACKENDS = ( | |
# Needed to login by username in Django admin, regardless of `allauth` | |
'django.contrib.auth.backends.ModelBackend', | |
# `allauth` specific authentication methods, such as login by e-mail | |
'allauth.account.auth_backends.AuthenticationBackend', | |
) | |
# also for allauth | |
SITE_ID = 2 | |
# disable this in production | |
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' | |
LOGIN_REDIRECT_URL = '/' | |
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL=None | |
ACCOUNT_EMAIL_REQUIRED=True | |
ACCOUNT_AUTHENTICATION_METHOD="email" | |
ACCOUNT_EMAIL_VERIFICATION = "optional" | |
# allauth end | |
WSGI_APPLICATION = 'togethere.wsgi.application' | |
# Database | |
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases | |
DATABASES = { | |
'default': { | |
'ENGINE': 'django.db.backends.sqlite3', | |
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), | |
} | |
} | |
# Password validation | |
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators | |
AUTH_PASSWORD_VALIDATORS = [ | |
{ | |
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', | |
}, | |
{ | |
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', | |
}, | |
{ | |
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', | |
}, | |
{ | |
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', | |
}, | |
] | |
# Internationalization | |
# https://docs.djangoproject.com/en/1.9/topics/i18n/ | |
LANGUAGE_CODE = 'en-us' | |
TIME_ZONE = 'Europe/Amsterdam' | |
USE_I18N = True | |
USE_L10N = True | |
USE_TZ = True | |
# Static files (CSS, JavaScript, Images) | |
# https://docs.djangoproject.com/en/1.9/howto/static-files/ | |
STATIC_URL = '/static/' | |
STATIC_ROOT = os.path.join(BASE_DIR, 'static') | |
os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = 'localhost:8123' | |
# TinyMCE configuration | |
TINYMCE_JS_URL = os.path.join(STATIC_URL, "articles/build/lib/node_modules/tinymce/tinymce.min.js") | |
TINYMCE_JS_ROOT = os.path.join(STATIC_ROOT, "articles/build/lib/node_modules/tinymce") | |
TINYMCE_COMPRESSOR = False | |
TINYMCE_DEFAULT_CONFIG = { | |
'theme': "modern", | |
'toolbar': "undo redo | bold italic | bullist numlist | blockquote | removeformat", | |
'menubar': False, | |
'statusbar': False, | |
'schema': "html5", | |
'max_height': 500, | |
'max_width': 500, | |
'min_height': 100, | |
'min_width': 400 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""togethere URL Configuration | |
The `urlpatterns` list routes URLs to views. For more information please see: | |
https://docs.djangoproject.com/en/1.9/topics/http/urls/ | |
Examples: | |
Function views | |
1. Add an import: from my_app import views | |
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') | |
Class-based views | |
1. Add an import: from other_app.views import Home | |
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') | |
Including another URLconf | |
1. Import the include() function: from django.conf.urls import url, include | |
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) | |
""" | |
from django.conf.urls import include, url | |
from django.contrib import admin | |
from allauth.account import views | |
urlpatterns = [ | |
url(r'^admin/', admin.site.urls), | |
url(r"^accounts/register/$", views.signup, name="account_signup"), | |
url(r'^accounts/', include('allauth.urls')), | |
url(r'^tinymce/', include('tinymce.urls')), | |
url(r'', include('articles.urls')), | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.shortcuts import render, get_object_or_404 | |
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | |
from django.http import HttpResponseRedirect | |
from django.core.urlresolvers import reverse, reverse_lazy | |
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView | |
from .models import Article, Category, City, Profile | |
from .forms import ArticleForm | |
class ArticlesView(ListView): | |
model = Article | |
context_object_name = 'articles' | |
paginate_by = 25 | |
template_name = 'articles/articles.html' | |
def get_context_data(self, **kwargs): | |
context = super(ArticlesView, self).get_context_data(**kwargs) | |
context['form'] = ArticleForm | |
return context | |
class ArticleView(DetailView): | |
model = Article | |
template_name = 'articles/article.html' | |
class ArticleSubmitView(CreateView): | |
model = Article | |
form_class = ArticleForm | |
template_name = 'articles/article-submit.html' | |
# set up login required later | |
# @method_decorator(login_required) | |
# def dispatch(self, *args, **kwargs): | |
# return super(ArticleSubmitView, self).dispatch(*args, **kwargs) | |
def form_valid(self, form): | |
obj = form.save(commit=False) | |
obj.author = self.request.user | |
obj.save() | |
form.save_m2m() | |
return HttpResponseRedirect(reverse('article', kwargs={'pk': obj.id})) | |
class ArticleUpdateView(UpdateView): | |
model = Article | |
form_class = ArticleForm | |
template_name_suffix = '-update' | |
def form_valid(self, form): | |
obj = form.save(commit=False) | |
obj.author = self.request.user | |
obj.save() | |
form.save_m2m() | |
return HttpResponseRedirect(reverse('article', kwargs={'pk': obj.id})) | |
class ArticleDeleteView(DeleteView): | |
model = Article | |
success_url = reverse_lazy('articles') | |
template_name_suffix = '-delete' | |
class CategoriesView(ListView): | |
model = Category | |
context_object_name = 'categories' | |
template_name = 'articles/categories.html' | |
class CategoryView(ListView): | |
model = Article | |
context_object_name = 'articles' | |
paginate_by = 25 | |
def get_context_data(self, **kwargs): | |
# Call the base implementation first to get a context | |
context = super(CategoryView, self).get_context_data(**kwargs) | |
# Add in a QuerySet of the category | |
context['category'] = Category.objects.get(pk=self.kwargs['pk']) | |
return context | |
def get_queryset(self): | |
return Article.objects.filter(categories=self.kwargs['pk']) | |
template_name = 'articles/category.html' | |
class CitiesView(ListView): | |
model = City | |
context_object_name = 'cities' | |
template_name = 'articles/cities.html' | |
class CityView(ListView): | |
model = Article | |
context_object_name = 'articles' | |
paginate_by = 25 | |
def get_context_data(self, **kwargs): | |
# Call the base implementation first to get a context | |
context = super(CityView, self).get_context_data(**kwargs) | |
# Add in a QuerySet of the city | |
context['city'] = City.objects.get(pk=self.kwargs['pk']) | |
return context | |
def get_queryset(self): | |
return Article.objects.filter(city=self.kwargs['pk']) | |
template_name = 'articles/city.html' | |
class ProfileView(ListView): | |
model = Article | |
context_object_name = 'articles' | |
paginate_by = 25 | |
def get_context_data(self, **kwargs): | |
context = super(ProfileView, self).get_context_data(**kwargs) | |
context['profile'] = get_object_or_404(Profile, pk=self.kwargs['pk']) | |
return context | |
def get_queryset(self): | |
return Article.objects.filter(author__id=self.kwargs['pk']) | |
template_name = 'articles/profile.html' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment