add deployment and etc

master
fefa4ka 11 years ago
parent d6fabb78ca
commit d03d77a66a
  1. 0
      app/__init__.py
  2. 210
      app/conf/newrelic.ini
  3. 22
      app/conf/nginx.conf.template
  4. 15
      app/conf/uwsgi_params
  5. 14
      app/conf/uwsgi_zuykov.conf.template
  6. 0
      app/deploy/__init__.py
  7. 107
      app/deploy/debian.py
  8. 24
      app/deploy/django.py
  9. 17
      app/deploy/hosts.py
  10. 26
      app/deploy/service.py
  11. 167
      app/deploy/tasks.py
  12. 88
      app/deploy/zuykov.py
  13. 20
      app/settings.py
  14. 3
      app/urls.py
  15. 54
      blog/migrations/0009_auto_20150726_2021.py
  16. 4
      blog/urls.py
  17. 30
      deploy.py
  18. 2
      manage.py
  19. 2
      requirements.txt
  20. 0
      service/__init__.py
  21. 15
      service/cms_app.py
  22. 75
      service/cms_appconfig.py
  23. 58
      service/cms_plugins.py
  24. 10
      service/urls.py
  25. 52
      service/views.py
  26. BIN
      zsite/static/imgs/phone.png
  27. 2
      zsite/static/js/app.js
  28. 52
      zsite/static/js/forms.js
  29. 18
      zsite/static/less/about.less
  30. 40
      zsite/static/less/consultation.less
  31. 1
      zsite/static/less/main.less
  32. 2
      zsite/static/less/people.less
  33. 2
      zsite/templates/aldryn_people/plugins/feature/people_list.html
  34. 21
      zsite/templates/base.html
  35. 70
      zsite/templates/form_template/consultation.html
  36. 9
      zsite/templates/menu.html
  37. 14
      zsite/templates/menu_header.html
  38. 5
      zsite/templates/sub_section.html

@ -0,0 +1,210 @@
# ---------------------------------------------------------------------------
#
# This file configures the New Relic Python Agent.
#
# The path to the configuration file should be supplied to the function
# newrelic.agent.initialize() when the agent is being initialized.
#
# The configuration file follows a structure similar to what you would
# find for Microsoft Windows INI files. For further information on the
# configuration file format see the Python ConfigParser documentation at:
#
# http://docs.python.org/library/configparser.html
#
# For further discussion on the behaviour of the Python agent that can
# be configured via this configuration file see:
#
# http://newrelic.com/docs/python/python-agent-configuration
#
# ---------------------------------------------------------------------------
# Here are the settings that are common to all environments.
[newrelic]
# You must specify the license key associated with your New
# Relic account. This key binds the Python Agent's data to your
# account in the New Relic service.
license_key = 7a0c5c3cda7e345c16a596d31a7f1fe8dc9c2ee7
# The appplication name. Set this to be the name of your
# application as you would like it to show up in New Relic UI.
# The UI will then auto-map instances of your application into a
# entry on your home dashboard page.
app_name = Transcribe.ninja
# When "true", the agent collects performance data about your
# application and reports this data to the New Relic UI at
# newrelic.com. This global switch is normally overridden for
# each environment below.
monitor_mode = true
# Sets the name of a file to log agent messages to. Useful for
# debugging any issues with the agent. This is not set by
# default as it is not known in advance what user your web
# application processes will run as and where they have
# permission to write to. Whatever you set this to you must
# ensure that the permissions for the containing directory and
# the file itself are correct, and that the user that your web
# application runs as can write to the file. If not able to
# write out a log file, it is also possible to say "stderr" and
# output to standard error output. This would normally result in
# output appearing in your web server log.
#log_file = /tmp/newrelic-python-agent.log
# Sets the level of detail of messages sent to the log file, if
# a log file location has been provided. Possible values, in
# increasing order of detail, are: "critical", "error", "warning",
# "info" and "debug". When reporting any agent issues to New
# Relic technical support, the most useful setting for the
# support engineers is "debug". However, this can generate a lot
# of information very quickly, so it is best not to keep the
# agent at this level for longer than it takes to reproduce the
# problem you are experiencing.
log_level = info
# The Python Agent communicates with the New Relic service using
# SSL by default. Note that this does result in an increase in
# CPU overhead, over and above what would occur for a non SSL
# connection, to perform the encryption involved in the SSL
# communication. This work is though done in a distinct thread
# to those handling your web requests, so it should not impact
# response times. You can if you wish revert to using a non SSL
# connection, but this will result in information being sent
# over a plain socket connection and will not be as secure.
ssl = true
# High Security Mode enforces certain security settings, and
# prevents them from being overridden, so that no sensitive data
# is sent to New Relic. Enabling High Security Mode means that
# SSL is turned on, request parameters are not collected, and SQL
# can not be sent to New Relic in its raw form. To activate High
# Security Mode, it must be set to 'true' in this local .ini
# configuration file AND be set to 'true' in the server-side
# configuration in the New Relic user interface. For details, see
# https://docs.newrelic.com/docs/subscriptions/high-security
high_security = false
# The Python Agent will attempt to connect directly to the New
# Relic service. If there is an intermediate firewall between
# your host and the New Relic service that requires you to use a
# HTTP proxy, then you should set both the "proxy_host" and
# "proxy_port" settings to the required values for the HTTP
# proxy. The "proxy_user" and "proxy_pass" settings should
# additionally be set if proxy authentication is implemented by
# the HTTP proxy. The "proxy_scheme" setting dictates what
# protocol scheme is used in talking to the HTTP proxy. This
# would normally always be set as "http" which will result in the
# agent then using a SSL tunnel through the HTTP proxy for end to
# end encryption.
# proxy_scheme = http
# proxy_host = hostname
# proxy_port = 8080
# proxy_user =
# proxy_pass =
# Tells the transaction tracer and error collector (when
# enabled) whether or not to capture the query string for the
# URL and send it as the request parameters for display in the
# UI. When "true", it is still possible to exclude specific
# values from being captured using the "ignored_params" setting.
capture_params = false
# Space separated list of variables that should be removed from
# the query string captured for display as the request
# parameters in the UI.
ignored_params =
# The transaction tracer captures deep information about slow
# transactions and sends this to the UI on a periodic basis. The
# transaction tracer is enabled by default. Set this to "false"
# to turn it off.
transaction_tracer.enabled = true
# Threshold in seconds for when to collect a transaction trace.
# When the response time of a controller action exceeds this
# threshold, a transaction trace will be recorded and sent to
# the UI. Valid values are any positive float value, or (default)
# "apdex_f", which will use the threshold for a dissatisfying
# Apdex controller action - four times the Apdex T value.
transaction_tracer.transaction_threshold = apdex_f
# When the transaction tracer is on, SQL statements can
# optionally be recorded. The recorder has three modes, "off"
# which sends no SQL, "raw" which sends the SQL statement in its
# original form, and "obfuscated", which strips out numeric and
# string literals.
transaction_tracer.record_sql = obfuscated
# Threshold in seconds for when to collect stack trace for a SQL
# call. In other words, when SQL statements exceed this
# threshold, then capture and send to the UI the current stack
# trace. This is helpful for pinpointing where long SQL calls
# originate from in an application.
transaction_tracer.stack_trace_threshold = 0.5
# Determines whether the agent will capture query plans for slow
# SQL queries. Only supported in MySQL and PostgreSQL. Set this
# to "false" to turn it off.
transaction_tracer.explain_enabled = true
# Threshold for query execution time below which query plans
# will not not be captured. Relevant only when "explain_enabled"
# is true.
transaction_tracer.explain_threshold = 0.5
# Space separated list of function or method names in form
# 'module:function' or 'module:class.function' for which
# additional function timing instrumentation will be added.
transaction_tracer.function_trace =
# The error collector captures information about uncaught
# exceptions or logged exceptions and sends them to UI for
# viewing. The error collector is enabled by default. Set this
# to "false" to turn it off.
error_collector.enabled = true
# To stop specific errors from reporting to the UI, set this to
# a space separated list of the Python exception type names to
# ignore. The exception name should be of the form 'module:class'.
error_collector.ignore_errors =
# Browser monitoring is the Real User Monitoring feature of the UI.
# For those Python web frameworks that are supported, this
# setting enables the auto-insertion of the browser monitoring
# JavaScript fragments.
browser_monitoring.auto_instrument = true
# A thread profiling session can be scheduled via the UI when
# this option is enabled. The thread profiler will periodically
# capture a snapshot of the call stack for each active thread in
# the application to construct a statistically representative
# call tree.
thread_profiler.enabled = true
# ---------------------------------------------------------------------------
#
# The application environments. These are specific settings which
# override the common environment settings. The settings related to a
# specific environment will be used when the environment argument to the
# newrelic.agent.initialize() function has been defined to be either
# "development", "test", "staging" or "production".
#
[newrelic:development]
monitor_mode = false
[newrelic:test]
monitor_mode = false
[newrelic:staging]
app_name = Zuykov.com
monitor_mode = true
[newrelic:production]
monitor_mode = true
# ---------------------------------------------------------------------------

@ -0,0 +1,22 @@
upstream django_zuykov {
server unix:///home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/wsgi_transcribe_ninja.sock;
}
server {
listen 80;
server_name dev.zuykov.com;
charset utf-8;
client_max_body_size 1024M;
location /static {
alias /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/static;
}
location / {
uwsgi_pass django_zuykov;
include /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/uwsgi_params;
}
}

@ -0,0 +1,15 @@
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;

@ -0,0 +1,14 @@
[uwsgi]
uid=%(SERVER_USERNAME)s
gid=%(SERVER_USERNAME)s
chdir = /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s
module = app.wsgi_zuykov
home = /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/env
eval = import newrelic.agent, wsgi_zuykov; application = newrelic.agent.wsgi_application()(wsgi_zuykov.application)
master = true
processes = 4
socket = /home/%(EC2_SERVER_USERNAME)s/%(PROJECT_NAME)s/app/wsgi_zuykov.sock
chmod-socket = 666
vacuum = true

@ -0,0 +1,107 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from app import settings
from deployer.node import Node
from deployer.utils import esc1
class Debian(Node):
def _configure_instance(self, tasks):
# Configure the instance that was just created
for item in tasks:
try:
print item['message']
except KeyError:
pass
getattr(self, "_" + item['action'])(item['params'])
# Actions
# def _virtualenv(params):
# """
# Allows running commands on the server
# with an active virtualenv
# """
# with cd(fabconf['APPS_DIR']):
# _virtualenv_command(_render(params))
def _apt(self, params):
"""
Runs apt-get install commands
"""
for pkg in params:
self._sudo("apt-get install -y -qq %s" % pkg)
def _pip(self, params):
"""
Runs pip install commands
"""
for pkg in params:
self._sudo("pip install %s" % pkg)
def _run(self, params):
"""
Runs command with active user
"""
command = self._render(params)
self.hosts.run(command)
def _sudo(self, params):
"""
Run command as root
"""
command = self._render(params)
self.hosts.sudo(command)
def _put(self, params):
"""
Moves a file from local computer to server
"""
for host in self.hosts.get_hosts():
host = host()
host.put_file(
self._render(params['file']),
self._render(params['destination'])
)
def _put_template(self, params, context=settings.__dict__):
"""
Same as _put() but it loads a file and does variable replacement
"""
f = open(self._render(params['template']), 'r')
template = f.read()
self.hosts.run(
self._write_to(
self._render(template, context),
self._render(params['destination'])
)
)
def _render(self, template, context=settings.__dict__):
"""
Does variable replacement
"""
return template % context
def _write_to(self, string, path):
"""
Writes a string to a file on the server
"""
return "echo '" + string + "' > " + path
def _append_to(self, string, path):
"""
Appends to a file on the server
"""
return "echo '" + string + "' >> " + path
def _virtualenv(self, command):
"""
Activates virtualenv and runs command
"""
with self.hosts.prefix(settings.ACTIVATE):
with self.hosts.cd(settings.PROJECT_DIR, expand=True):
self.hosts.run(self._render(command))

@ -0,0 +1,24 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# from app import settings
# from deployer.node import Node
from deployer.utils import esc1
from app.deploy.debian import Debian
class DjangoDeployment(Debian):
def run_management_command(self, command):
""" Run Django management command in virtualenv. """
self._virtualenv('./manage.py %s' % esc1(command))
def django_shell(self):
""" Open interactive Django shell. """
self.run_management_command('shell')
def python_packages_install(self):
""" Run Django management command in virtualenv. """
# Activate the virtualenv.
self._virtualenv('pip install --upgrade pip && pip install -r %(PROJECT_DIR)s/requirements.txt --upgrade' % settings.__dict__)

@ -0,0 +1,17 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Deploy
from deployer.host import SSHHost
from zsite import settings
class WebHost(SSHHost):
slug = 'web'
address = 'dev.zuykov.com'
username = 'web'
password = '9oijffDf2vi@D!'
class DatabaseHost(WebHost):
slug = 'database'

@ -0,0 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from deployer.node import Node, required_property
from deployer.utils import esc1
class UpstartService(Node):
"""
Abstraction for any upstart service with start/stop/status methods.
"""
name = required_property()
def start(self):
self.hosts.sudo('service %s start' % esc1(self.name))
def stop(self):
self.hosts.sudo('service %s stop' % esc1(self.name))
def restart(self):
self.stop()
self.start()
def status(self):
self.hosts.sudo('service %s status' % esc1(self.name))

@ -0,0 +1,167 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
--------------------------------------------------------------------------------------
tasks.py
--------------------------------------------------------------------------------------
A set of tasks to manage your AWS Django deployment.
author : Ashok Fernandez (github.com/ashokfernandez/)
credit : Derived from files in https://github.com/gcollazo/Fabulous
date : 11 / 3 / 2014
Tasks include:
- configure_instance : Configures a new EC2 instance (as definied in settings.py) and return's it's public dns
This takes around 8 minutes to complete.
- update_packages : Updates the python packages on the server to match those found in requirements/common.txt and
requirements/prod.txt
- deploy : Pulls the latest commit from the master branch on the server, collects the static files, syncs the db and
restarts the server
- reload_gunicorn : Pushes the gunicorn startup script to the servers and restarts the gunicorn process, use this if you
have made changes to templates/start_gunicorn.bash
- reload_nginx : Pushes the nginx config files to the servers and restarts the nginx, use this if you
have made changes to templates/nginx-app-proxy or templates/nginx.conf
- reload_supervisor : Pushes the supervisor config files to the servers and restarts the supervisor, use this if you
have made changes to templates/supervisord-init or templates/supervisord.conf
'''
# Spawns a new EC2 instance (as definied in djangofab_conf.py) and return's it's public dns
# This takes around 8 minutes to complete.
common_configure = [
# First command as regular user
{"action": "run", "params": "whoami"},
# List of APT packages to install
{"action": "apt",
"params": ["libpq-dev", "git",
"python-setuptools", "python-dev", "build-essential", "python-pip", "redis-server",
"libmysqlclient-dev", "subversion"],
"message":"Installing apt-get packages" },
# List of pypi packages to install
{"action": "pip", "params": ["virtualenv"],
"message":"Installing virtualenv"},
#project directory
{"action": "run", "params": "mkdir -p %(PROJECT_DIR)s", "message": "Create project folder" },
{"action": "run", "params": "mkdir -p %(LOGS_DIR)s", "message": "Create logs folder" },
{"action": "sudo", "params": "chown -R %(SERVER_USERNAME)s: %(PROJECT_DIR)s"},
# git setup
{"action": "run", "params": "git config --global user.name '%(GIT_USERNAME)s'",
"message": "Configuring git"},
{"action": "run",
"params": "git config --global user.email '%(ADMIN_EMAIL)s'"},
{"action": "put", "params": {"file": "%(GIT_KEY_PATH)s",
"destination": "/home/%(SERVER_USERNAME)s/.ssh/%(GIT_KEY_NAME)s"}},
{"action": "run", "params":
"chmod 600 /home/%(SERVER_USERNAME)s/.ssh/%(GIT_KEY_NAME)s"},
{"action": "run", "params":
u"""echo 'IdentityFile /home/%(SERVER_USERNAME)s/.ssh/%(GIT_KEY_NAME)s' >> /home/%(SERVER_USERNAME)s/.ssh/config"""},
{"action": "run", "params":
"ssh-keyscan github.com >> /home/%(SERVER_USERNAME)s/.ssh/known_hosts"},
# Clone the git repo
{"action": "run",
"params": "git clone %(REPOSITORY)s %(PROJECT_DIR)s"},
# virtualenv
{"action": "run",
"params": "mkdir -p %(ENV_DIR)s", "message": "Create project folder" },
{"action": "run",
"params": "virtualenv %(ENV_DIR)s", "message": "Configuring virtualenv" },
{"action": "sudo", "params": "chown -R %(SERVER_USERNAME)s: %(ENV_DIR)s"},
# {"action": "run", "params":
# "echo 'expo WORKON_HOME=%(PRO_DIR)s' >> /home/%(SERVER_USERNAME)s/.profile"},
{"action": "run", "params":
u"echo 'source %(ENV_DIR)s/bin/activate' >> /home/%(SERVER_USERNAME)s/.profile"},
{"action": "run", "params": "source /home/%(SERVER_USERNAME)s/.profile"},
{"action": "virtualenv", "params":
"pip install -r %(PROJECT_DIR)s/requirements.txt --upgrade"},
]
web_configure = [
# List of APT packages to install
{"action": "apt",
"params": ["nginx", "uwsgi", "uwsgi-plugin-python", "nodejs", "npm"],
"message":"Installing nginx, uwsgi, nodejs packages"},
{"action": "sudo", "params": "npm install -g bower karma grunt grunt-cli"},
# Костыль с нодой
{"action": "run", "params": "ln -s /usr/bin/nodejs %(ENV_DIR)s/bin/node"},
{"action": "sudo", "params": "cd %(PROJECT_DIR)s/frontend/transcribe.ninja && npm install"},
{"action": "sudo", "params": "cd %(PROJECT_DIR)s/frontend/stenograph.us && npm install"},
{"action": "sudo", "params": "rm -rf /etc/nginx/sites-enabled/default"},
{"action": "sudo", "params": "rm -rf /etc/supervisor/conf.d/default"},
{"action": "sudo", "params": "rm -rf /etc/uwsgi/apps-enabled/default.ini"},
]
npm_install = [
{"action": "sudo", "params": "cd %(PROJECT_DIR)s/frontend/transcribe.ninja && npm install"},
{"action": "sudo", "params": "cd %(PROJECT_DIR)s/frontend/stenograph.us && npm install"},
]
# nginx
reload_nginx = [
{"action": "put_template", "params": {"template": "%(BASE_DIR)s/app/conf/nginx.conf.template",
"destination": "/home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/nginx.conf"}},
{"action": "sudo", "params": "service nginx restart",
"message": "Restarting nginx"},
]
create_nginx_links = [
{"action": "sudo", "params":
"ln -s /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/nginx.conf /etc/nginx/sites-enabled/%(PROJECT_NAME)s.conf"},
]
create_uwsgi_links = [
{"action": "sudo", "params":
"ln -s /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/uwsgi_stenograph_us.conf /etc/uwsgi/apps-enabled/%(PROJECT_NAME)s_stenograph_us.ini"},
{"action": "sudo", "params":
"ln -s /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/uwsgi_transcribe_ninja.conf /etc/uwsgi/apps-enabled/%(PROJECT_NAME)s_transcribe_ninja.ini"},
]
reload_uwsgi = [
{"action": "put_template", "params": {"template": "%(BASE_DIR)s/app/conf/uwsgi_stenograph_us.conf.template",
"destination": "/home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/uwsgi_stenograph_us.conf"}},
{"action": "put_template", "params": {"template": "%(BASE_DIR)s/app/conf/uwsgi_transcribe_ninja.conf.template",
"destination": "/home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/uwsgi_transcribe_ninja.conf"}},
{"action": "sudo", "params": "service uwsgi restart",
"message": "Restarting uwsgi"},
]
web_configure += reload_uwsgi + reload_nginx + create_uwsgi_links + create_nginx_links
engine_configure = [
# List of pypi packages to install
{"action": "run", "params": "cp -r ~/%(PROJECT_NAME)s/env/share/voiceid ~/%(PROJECT_NAME)s/env/local/share/",
"message":"Move voiceid"},
{"action": "apt", "params": ["supervisor"],
"message":"Installing supervisor"},
{"action": "put_template", "params": {"template": "%(BASE_DIR)s/app/conf/supervisor.conf.template",
"destination": "/home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/supervisor.conf"}},
{"action": "sudo", "params":
"ln -s /home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/supervisor.conf /etc/supervisor/conf.d/%(PROJECT_NAME)s.conf"},
{"action": "sudo", "params": "service supervisor restart",
"message": "Restarting supervisor"},
# Запстить очереди
# TODO: настроить редис как внешний сервер
]
reload_supervisor = [
{"action": "put_template", "params": {"template": "%(BASE_DIR)s/app/conf/supervisor.conf.template",
"destination": "/home/%(SERVER_USERNAME)s/%(PROJECT_NAME)s/app/conf/supervisor.conf"}},
{"action": "sudo", "params": "service supervisor restart",
"message": "Restarting supervisor"},
]

@ -0,0 +1,88 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# from django.db import connection
from deployer.node import Node, map_roles
from deployer.utils import esc1
from app.deploy.service import *
from app.deploy.django import *
import app.deploy.tasks as tasks
import os.path
from app import settings
class ZuykovWebSystem(Node):
"""
The base definition of our web system.
roles: web, engine, database
"""
# @map_roles(host='database')
# class Database(<):
# def create(self):
# host = settings.DATABASES['default']
# # Создаём группу безопасности
# security_group = self._ec2_mysql_security_group()
# # Создаём группу параметров
# # Запускаем инстанс
# self._rds_create_instance(
# 'database',
# host['NAME'],
# host['USER'],
# host['PASSWORD'])
@map_roles(host='web')
class Application(DjangoDeployment):
def configure_base(self):
self._configure_instance(tasks.common_configure)
def hello(self):
self.hosts.run('echo hello world')
def update(self):
self.checkout()
self.pull()
def checkout(self, commit="."):
with self.hosts.cd(settings.PROJECT_DIR, expand=True):
self.hosts.run("git checkout '%s'" % esc1(commit))
def pull(self):
with self.hosts.cd(settings.PROJECT_DIR, expand=True):
self.hosts.run('git pull')
def create(self):
self.Application.hello()
# Если созданы — удалить
# # Предварительно спросить
# self.Frontend.create()
# self.Engine.create()
def deploy(self):
pass
# self.Application.update()
# self.Application.python_packages_install()
# self.update_hosts()
# self.Engine.migrate()
# self.Frontend.restart()
# self.Engine.restart()

@ -36,6 +36,19 @@ ALLOWED_HOSTS = []
# Application definition
PROJECT_NAME = 'zuykov'
SERVER_USERNAME = 'web'
PROJECT_DIR = '~/' + PROJECT_NAME
ENV_DIR = '%s/env' % PROJECT_DIR
LOGS_DIR = '~/logs'
ACTIVATE = '. %s/bin/activate' % ENV_DIR
REPOSITORY = 'git@github.com:fefa4ka/zuykov.git'
GIT_USERNAME = 'fefa4ka'
ADMIN_EMAIL = 'fefa4ka@gmail.com'
GIT_KEY_PATH = '/Users/fefa4ka/.ssh/deploy_rsa'
GIT_KEY_NAME = 'github_rsa'
@ -87,13 +100,17 @@ PIPELINE_JS = {
'main': {
'source_filenames': (
'js/app.js',
'js/forms.js',
),
'output_filename': 'js/*.js',
},
'vendor': {
'source_filenames': (
'vendor/angular/angular.js',
'vendor/angular-bootstrap/ui-bootstrap.js'
'vendor/angular-bootstrap/ui-bootstrap.js',
'vendor/angular-bootstrap/ui-bootstrap-tpls.js',
'vendor/jquery/dist/jquery.js',
),
'output_filename': 'js/vendor.js',
}
@ -201,6 +218,7 @@ INSTALLED_APPS = (
'aldryn_bootstrap3',
'djangocms_forms',
# 'debug_toolbar',
)

@ -9,12 +9,15 @@ from django.conf import settings
admin.autodiscover()
urlpatterns = i18n_patterns('',
url(r'^', include('djangocms_forms.urls')),
url(r'^admin/', include(admin.site.urls)), # NOQA
url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap',
{'sitemaps': {'cmspages': CMSSitemap}}),
url(r'^select2/', include('django_select2.urls')),
url(r'^', include('cms.urls')),
url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')),
)
# This is only needed when using runserver.

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('blog', '0008_auto_20150713_1609'),
]
operations = [
migrations.AlterModelOptions(
name='blogcategorytranslation',
options={'default_permissions': (), 'verbose_name': 'blog category Translation', 'managed': True},
),
migrations.AlterModelOptions(
name='posttranslation',
options={'default_permissions': (), 'verbose_name': 'blog article Translation', 'managed': True},
),
migrations.RemoveField(
model_name='latestpostsplugin',
name='tags',
),
migrations.AlterField(
model_name='blogcategorytranslation',
name='language_code',
field=models.CharField(max_length=15, verbose_name='Language', db_index=True),
preserve_default=True,
),
migrations.AlterField(
model_name='blogconfig',
name='category_slug',
field=models.CharField(help_text='Only category to display', max_length=255, verbose_name='Category slug', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='post',
name='enable_comments',
field=models.BooleanField(default=True, verbose_name='Enable comments on post'),
preserve_default=True,
),
migrations.AlterField(
model_name='posttranslation',
name='language_code',
field=models.CharField(max_length=15, verbose_name='Language', db_index=True),
preserve_default=True,
),
migrations.AlterUniqueTogether(
name='blogconfigtranslation',
unique_together=set([('language_code', 'master')]),
),
]

@ -1,10 +1,12 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
from django.conf.urls import patterns, include, url
from .views import (PostListView, PostDetailView, TaggedListView,
AuthorEntriesView, PostArchiveView, CategoryEntriesView)
from .feeds import LatestEntriesFeed, TagFeed
from djangocms_forms.views import FormSubmission
urlpatterns = patterns(
'',

@ -0,0 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.db import connection
from deployer.client import start
from deployer.node import Node
from app.deploy import hosts
from app.deploy.zuykov import ZuykovWebSystem
import app.settings as settings
class RootNode(Node):
"""
The root node of our configuration, containing two 'instances' of
`WebSystem`,
"""
class ProductionSystem(ZuykovWebSystem):
class Hosts:
web = {hosts.WebHost}
database = {hosts.DatabaseHost}
if __name__ == '__main__':
start(RootNode)

@ -3,7 +3,7 @@ import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zsite.settings")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
from django.core.management import execute_from_command_line

@ -19,4 +19,6 @@ djangocms_video
mysql
django-pipeline
django_debug_toolbar
djangocms-forms
django-multipleformwizard
#export C_INCLUDE_PATH=/usr/local/Cellar/libxml2/2.9.2/include/libxml2:$C_INCLUDE_PATH

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from aldryn_apphooks_config.app_base import CMSConfigApp
from cms.apphook_pool import apphook_pool
from django.utils.translation import ugettext_lazy as _
from .models import ServiceConfig
class BlogApp(CMSConfigApp):
app_config = ServiceConfig
name = _('Service')
urls = ['service.urls']
app_name = 'service'
apphook_pool.register(ServiceApp)

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django import forms
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
from aldryn_apphooks_config.utils import setup_config
from aldryn_apphooks_config.models import AppHookConfig
from app_data import AppDataForm
from parler.models import TranslatableModel
from parler.models import TranslatedFields
from cms.models.fields import PlaceholderField
class ServiceConfig(TranslatableModel, AppHookConfig):
"""Adds some translatable, per-app-instance fields."""
translations = TranslatedFields(
app_title=models.CharField(_('application title'), max_length=234),
)
category_slug = models.CharField(
_('Category slug'),
blank=True,
max_length=255,
help_text=_('Only category to display'))
placeholder_base_top = PlaceholderField(
'service_base_top',
related_name='service_base_top',
)
placeholder_base_sidebar = PlaceholderField(
'service_base_sidebar',
related_name='service_base_sidebar',
)
placeholder_list_top = PlaceholderField(
'service_list_top',
related_name='service_list_top',
)
placeholder_list_footer = PlaceholderField(
'service_list_footer',
related_name='service_list_footer',
)
placeholder_detail_top = PlaceholderField(
'service_detail_top',
related_name='service_detail_top',
)
placeholder_detail_bottom = PlaceholderField(
'service_detail_bottom',
related_name='service_detail_bottom',
)
placeholder_detail_footer = PlaceholderField(
'service_detail_footer',
related_name='service_detail_footer',
)
def get_app_title(self):
return getattr(self, 'app_title', _('untitled'))
class SeviceConfigForm(AppDataForm):
default_published = forms.BooleanField(
label=_(u'Post published by default'), required=False,
initial=getattr(settings, 'service_DEFAULT_PUBLISHED', True))
setup_config(ServiceConfigForm, ServiceConfig)

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
from cms.models.pluginmodel import CMSPlugin
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from .models import ContextServicePlugin
from .forms import ContextServiceForm
from .settings import get_setting
class SevicePlugin(CMSPluginBase):
module = 'Sevice'
class SeviceContextPlugin(SevicePlugin):
"""
Non cached plugin which returns the latest posts taking into account the
user / toolbar state
"""
render_template = 'sevice/plugins/context_services.html'
name = _('Context Services')
model = ContextServicePlugin
form = ContextServiceForm
filter_horizontal = ('categories',)
cache = False
def render(self, context, instance, placeholder):
context = super(SeviceContextPlugin, self).render(context, instance, placeholder)
context['services_list'] = instance.get_services(context['request'])
if instance.categories.exists():
context['category'] = instance.categories.all()[0].slug
else:
context['category'] = "all"
return context
class SeviceContextPluginCached(SevicePlugin):
"""
Cached plugin which returns the latest published posts
"""
render_template = 'sevice/plugins/context_services.html'
name = _('Context Services')
model = ContextServicePlugin
form = ContextServiceForm
filter_horizontal = ('categories',)
def render(self, context, instance, placeholder):
context = super(SeviceContextPluginCached, self).render(context, instance, placeholder)
context['posts_list'] = instance.get_posts()
return context
plugin_pool.register_plugin(SeviceContextPlugin)

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from .views import (ServiceDetailView)
urlpatterns = patterns(
'',
url(r'^(?P<service_slug>[\w\.@+-]+)/$', ServiceDetailView.as_view(), name='service-detail'),
)

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
from django.contrib.auth import get_user_model
from django.core.urlresolvers import resolve
from django.utils.timezone import now
from django.utils.translation import get_language
from django.views.generic import ListView, DetailView
from parler.views import ViewUrlMixin, TranslatableSlugMixin
from aldryn_apphooks_config.mixins import AppConfigMixin
from .models import Service, ServiceCategory, SERVICE_CURRENT_SERVICE_IDENTIFIER
from .settings import get_setting
User = get_user_model()
class BaseServiceView(ViewUrlMixin, AppConfigMixin):
def get_queryset(self):
language = get_language()
queryset = self.model._default_manager.active_translations(language_code=language)
print self.config
if self.config and self.config.category_slug:
self._category = ServiceCategory.objects.active_translations(get_language(), slug=self.config.category_slug).latest('pk')
queryset = queryset.filter(categories=self._category.pk)
if not getattr(self.request, 'toolbar', False) or not self.request.toolbar.edit_mode:
queryset = queryset.published()
return queryset.on_site()
def render_to_response(self, context, **response_kwargs):
response_kwargs['current_app'] = resolve(self.request.path).namespace
return super(BaseServiceView, self).render_to_response(context, **response_kwargs)
class ServiceDetailView(TranslatableSlugMixin, BaseServiceView, DetailView):
model = Service
context_object_name = 'post'
template_name = 'service/service_detail.html'
slug_field = 'slug'
view_url_name = 'service:service-detail'
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
context['meta'] = self.get_object().as_meta()
context['use_placeholder'] = get_setting('USE_PLACEHOLDER')
setattr(self.request, SERVICE_CURRENT_SERVICE_IDENTIFIER, self.get_object())
return context

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

@ -1 +1,3 @@
angular.module('zuykov', ['ui.bootstrap']);
console.log('Yep');

@ -0,0 +1,52 @@
angular.module('zuykov').controller('ModalFormCtrl', function ($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.animationsEnabled = true;
$scope.open = function (form_id) {
console.log('open');
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'modalFormTemplate-' + form_id + '.html',
controller: 'ModalFormInstanceCtrl',
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
})
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.
.controller('ModalFormInstanceCtrl', function ($scope, $modalInstance, items, $log, $timeout) {
$log.info('opened modal');
$timeout(function () {
$('.forms').djangocms_forms();
}, 1000);
$scope.ok = function () {
$modalInstance.close("params");
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});

@ -1,10 +1,24 @@
.about-map {
position: absolute;
z-index: 0;
width: 65%;
margin-left: 35%;
margin-top: -16%;
width: 65%;
@media (min-width: 0) {
display: none;
}
@media (min-width: @screen-md-min) {
display: block;
margin-left: 40%;
}
@media (min-width: @screen-lg-min) {
display: block;
margin-left: 35%;
}
img {
width: 100%;
}

@ -0,0 +1,40 @@
.modal-consultation {
img {
float: left;
width: 30%; }
.forms {
padding-left: 35%;
h3 {
margin-top: 18px;
}
label {
width: 25%;
}
.help-text {
margin-top: 10px;
margin-bottom: 5px;
}
button {
margin-top: 15px;
}
.form-success {
margin-top: 20px;
font-size: 22px;
}
}
}
.consultation {
.btn-consultation:extend(.btn-default, .btn-xs) {}
}
.content {
.btn-consultation:extend(.btn-primary) {}
}

@ -18,6 +18,7 @@
@import 'blog.less';
@import 'consultation.less';
@import url(http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic,700italic|Roboto+Slab:700,400&subset=cyrillic-ext,latin);

@ -25,7 +25,7 @@
.people-description {
width: 80%;
font-size: 16px;
font-size: 15px;
padding-top: 25px;
padding-left: 140px;

@ -1,4 +1,4 @@
{% load i18n thumbnail shuffle %}
{% load cms_tags i18n thumbnail shuffle %}
<div class="plugin plugin-people">
{% if people_groups %}

@ -1,7 +1,7 @@
{% load cms_tags staticfiles sekizai_tags menu_tags i18n %}
{% load cms_tags staticfiles sekizai_tags menu_tags i18n %}
{% load pipeline %}
<!doctype html>
<html>
<html ng-app="zuykov">
<head>
<meta charset="utf-8">
<title>{% block title %}Zuykov and partners{% endblock title %}</title>
@ -14,8 +14,10 @@
{% render_block "css" %}
</head>
<body>
{% cms_toolbar %}
<div class="container">
<div class="wrapper">
<div class="header-logo">
<a href="/">
@ -30,25 +32,18 @@
</ul>
<p class="city">{% trans 'Moscow' %}</p>
<div class="consultation">
<h5>{% trans 'Free Consultation' %} </h5>
<h3><nobr>+7 800 700-16-37</nobr></h3>
<button type="button" class="btn btn-default btn-xs">{% trans 'Callback' %}</button>
<div class="email">
<a href="mailto:info@zuykov.{% if current_language == "ru" %}ru{% else %}com{% endif %}">info@zuykov.{% if current_language == "ru" %}ru{% else %}com{% endif %}</a>
</div>
{% static_placeholder 'consultation' %}
</div>
</div>
</div>
<h4 class="header-menu-font">{% trans 'Our Services' %}</h4>
<div class="background-line-pattern"></div>
<ul class="list-unstyled list-inline header-menu header-menu-font">
{% show_menu 0 1 100 100 "menu.html" %}
</ul>
{% show_menu 0 1 100 100 "menu_header.html" %}
{% block content %}{% endblock content %}
<footer>
{% static_placeholder 'footer' %}
<div class="background-line-pattern"></div>
<div class="about">
<a href="/">

@ -0,0 +1,70 @@
{% load cms_tags djangocms_forms_tags i18n sekizai_tags staticfiles %}
<div ng-controller="ModalFormCtrl">
<script type="text/ng-template" id="modalFormTemplate-{{ instance.id }}.html">
<div class="modal-body modal-consultation">
<img src="{% with 'imgs/phone.png' as image_static %}{% static image_static %}{% endwith %}">
<div class="forms" id="{{ instance.form_id }}">
{% if instance.title %}
<h3 class="title">{{ instance.title }}</h3>
{% endif %}
{% if instance.description %}
<div class="description">
{{ instance.description|safe }}
</div>
{% endif %}
<div class="form-wrapper">
<form action="{{ form.submission_url }}" method="POST" enctype="multipart/form-data">
<div class="form-errors" style="display:none;"></div>
{% for field in form.visible_fields %}
<div class="field-wrapper {{ field|input_class }} {{ field.css_classes }}">
{% if field.help_text %}
<div id="help-text-{{ field.auto_id }}" class="help-text">{{ field.help_text|safe }}</div>
{% endif %}
<div class="field-errors" style="display:none;"></div>
{% if field|is_checkbox %}
{{ field }}
{% endif %}
<label for="{{ field.id_for_label }}">
{{ field.label }}
</label>
{% if not field|is_checkbox %}
{{ field }}
{% endif %}
</div>
{% endfor %}
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<div class="button-wrapper submit">
<button class="form-button btn btn-primary" type="submit" value="{{ instance.submit_btn_txt }}">{{ instance.submit_btn_txt }}</button>
</div>
</form>
</div>
<div class="form-success" style="display: none;">
{% if instance.post_submit_msg %}
<p>{{ instance.post_submit_msg|safe }}</p>
{% else %}
{% blocktrans %}
<h3>Submission successful</h3>
<p>Thank You! Your form has been successfully submitted!</p>
{% endblocktrans %}
{% endif %}
</div>
</div>
</div>
</form>
</div>
</script>
<button class="btn btn-consultation" ng-click="open('{{ instance.id }}')" value="">{{ instance.title }}</button>
</div>
{% addtoblock "js" %}
<script src="{% static 'js/djangocms_forms/libs/jquery.form.min.js' %}"></script>
<script src="{% static 'js/djangocms_forms/djangocms_forms.js' %}"></script>
{% endaddtoblock %}

@ -1,16 +1,7 @@
{% load i18n menu_tags cache %}
{% for child in children %}
<li {% if child.selected %}class="active"{% endif %}>
{% if child.children %}
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
{{ child.get_menu_title }} <span class="caret"></span>
</a>
<ul class="dropdown-menu">
{% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
</ul>
{% else %}
<a href="{{ child.get_absolute_url }}"><span>{{ child.get_menu_title }}</span></a>
{% endif %}
</li>
{% if class and forloop.last and not forloop.parentloop %}{% endif %}
{% endfor %}

@ -0,0 +1,14 @@
{% load i18n menu_tags cache %}
{{ children.count }}
{% if children|length > 1 %}
<h4 class="header-menu-font">{% trans 'Our Services' %}</h4>
<div class="background-line-pattern"></div>
<ul class="list-unstyled list-inline header-menu header-menu-font">
{% for child in children %}
<li {% if child.selected %}class="active"{% endif %}>
<a href="{{ child.get_absolute_url }}"><span>{{ child.get_menu_title }}</span></a>
</li>
{% if class and forloop.last and not forloop.parentloop %}{% endif %}
{% endfor %}
</ul>
{% endif %}

@ -1,5 +1,5 @@
{% extends "base.html" %}
{% load cms_tags i18n menu_tags %}
{% load cms_tags i18n menu_tags %}
{% block title %}{% page_attribute "page_title" %}{% endblock title %}
@ -14,7 +14,8 @@
<div class="menu">
<h5>{% show_breadcrumb 0 "menu/sub_menu_title.html" 0 %}</h5>
<ul class="list-unstyled">
{% show_menu 1 0 100 100 'menu.html' %}
{{ node.level }}
{% show_menu 1 100 0 1 'menu.html' %}
</ul>
</div>
<div class="content">

Loading…
Cancel
Save