diff --git a/accounts/models.py b/accounts/models.py
index ce4e4b47..2c83a17b 100644
--- a/accounts/models.py
+++ b/accounts/models.py
@@ -144,6 +144,9 @@ class User(AbstractBaseUser, PermissionsMixin):
class Meta:
ordering=['-rating']
+ def is_organiser(self):
+ return bool(self.organiser)
+
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
diff --git a/core/models.py b/core/models.py
index 6d20823b..56d75875 100644
--- a/core/models.py
+++ b/core/models.py
@@ -4,7 +4,7 @@ from django.shortcuts import get_object_or_404
from django.db import models
from exposition.models import Exposition
-from settings.models import create_transl_fields
+import copy
from theme.models import Theme
from country.models import Country
from city.models import City
@@ -114,22 +114,38 @@ class Page(TranslatableModel):
def get_absolute_url(self):
return reverse('page_view', args=[self.url])
+ def __init__(self, *args, **kwargs):
+ super(Page, self).__init__(*args, **kwargs)
+ self.cache_fields = ['h1', 'body','title', 'description', 'keywords']
+ self.var_cache = {var: copy.copy(getattr(self, var)) for var in self.cache_fields}
+ self.is_new = True
+
def save(self, *args, **kwargs):
super(Page,self).save(*args, **kwargs)
-
- all_field_names = list(self._translated_field_names)
- clear_f_n = list(set(all_field_names) - {'master', 'master_id', 'id', 'language_code'})
- field_items = {}
- for fname in clear_f_n:
- field_items[fname] = getattr(self, fname)
-
- langs = [lan[0] for lan in settings.LANGUAGES]
- for lang in langs:
- if lang not in self.get_available_languages():
- self.translate(lang)
- for key, value in field_items.items():
- setattr(self, key, value)
- self.save_translations(self)
+ self.initial_language = 'ru'
+
+ new_values = {field: getattr(self, field) for field in self.cache_fields}
+ langs = [code for code, _ in settings.LANGUAGES]
+ if self.is_new:
+ for lang in langs:
+ if lang not in self.get_available_languages():
+ self.translate(lang)
+ for key, value in new_values.items():
+ setattr(self, key, value)
+ self.save_translations(self)
+ else:
+ translations = {obj.language_code:obj for obj in list(self.translations.all())}
+ for lang in langs:
+ if lang is not self.initial_language:
+ tr = translations[lang]
+ for key, value in new_values.items():
+ #if u'%s' % getattr(self, key) is u'' or getattr(self, key) is u'%s' % self.var_cache[key]:
+ setattr(tr, key, value)
+ tr.save()
+
+ self.lazy_translation_getter(self.initial_language)
+ self.var_cache = {var: copy.copy(getattr(self, var)) for var in self.cache_fields}
+ self.is_new = False
return self
def __unicode__(self):
diff --git a/meta/forms.py b/meta/forms.py
index 641845f4..fd3c009a 100644
--- a/meta/forms.py
+++ b/meta/forms.py
@@ -46,13 +46,14 @@ class MetaForm(forms.Form):
fill_with_signal(MetaSetting, meta, data)
meta.save()
+
class MetaFilterForm(AdminFilterForm):
model = MetaSetting
class SeoTextForm(TranslatableModelForm):
-
+ # lang = forms.ChoiceField(choices=settings.LANGUAGES)
class Meta:
model = SeoText
- fields = ['url', 'title', 'body']
- widgets = {'body':CKEditorWidget}
\ No newline at end of file
+ fields = ['url', 'title', 'page_title', 'description', 'body']
+ widgets = {'body': CKEditorWidget}
diff --git a/meta/models.py b/meta/models.py
index a8037849..98c6c5cd 100644
--- a/meta/models.py
+++ b/meta/models.py
@@ -142,11 +142,12 @@ class SeoTextManager(TranslationManager):
class SeoText(TranslatableModel):
- cache_fields = ['title', 'body']
- url = models.CharField(max_length=50, unique=True, verbose_name=u"URL: expomap.ru")
+ url = models.CharField(max_length=50, unique=True, verbose_name=u"URL: www.expomap.ru")
translations = TranslatedFields(
title=models.CharField(max_length=255, verbose_name=u"Заголовок"),
+ page_title=models.CharField(max_length=255, verbose_name=u"Тайтл страницы"),
+ description=models.CharField(max_length=1000, verbose_name=u"Дескрипшн"),
body=models.TextField(verbose_name=u"Текст")
)
@@ -154,36 +155,38 @@ class SeoText(TranslatableModel):
def __init__(self, *args, **kwargs):
super(SeoText, self).__init__(*args, **kwargs)
+ self.cache_fields = ['title', 'body', 'page_title', 'description']
self.is_new = True
- self.var_cache = {var: copy.copy(getattr(self, var)) for var in SeoText.cache_fields}
def get_absolute_url(self):
- return reverse_lazy('seo_all')
+ return self.url
def save(self, *args, **kwargs):
- init_lang = self.language_code
- self.is_new = bool(self.id)
- if not self.is_new: super(SeoText, self).save(*args, **kwargs)
-
- field_items = {}
- for fname in self.cache_fields:
- field_items[fname] = getattr(self, fname)
-
- langs = [l[0] for l in settings.LANGUAGES]
- for lang in langs:
- if lang not in self.get_available_languages():
- self.translate(lang)
- for key, value in field_items.items():
- if getattr(self, key) is '' or getattr(self, key) is self.var_cache[key]:
+ super(SeoText, self).save(*args, **kwargs)
+ self.initial_language = 'ru'
+
+ new_values = {field: getattr(self, field) for field in self.cache_fields}
+ langs = [code for code, _ in settings.LANGUAGES]
+ if self.is_new:
+ for lang in langs:
+ if lang not in self.get_available_languages():
+ self.translate(lang)
+ for key, value in new_values.items():
setattr(self, key, value)
-
- if self.is_new:
self.save_translations(self)
- else:
- super(SeoText, self).save(*args, **kwargs)
-
- self.translate(init_lang)
- self.var_cache = {var: copy.copy(getattr(self, var)) for var in SeoText.cache_fields}
+ else:
+ translations = {obj.language_code:obj for obj in list(self.translations.all())}
+ for lang in langs:
+ if lang is not self.initial_language:
+ tr = translations[lang]
+ for key, value in new_values.items():
+ #if u'%s' % getattr(self, key) is u'' or getattr(self, key) is u'%s' % self.var_cache[key]:
+ setattr(tr, key, value)
+ tr.save()
+
+ self.lazy_translation_getter(self.initial_language)
+ self.var_cache = {var: copy.copy(getattr(self, var)) for var in self.cache_fields}
+ self.is_new = False
return self
def __unicode__(self):
diff --git a/meta/views.py b/meta/views.py
index f8639343..81db7390 100644
--- a/meta/views.py
+++ b/meta/views.py
@@ -208,6 +208,7 @@ class EditSeoText(UpdateView):
template_name = "admin/meta/create_seo_text.html"
+
class DeleteSeoText(DeleteView):
model = SeoText
template_name = "admin/meta/seo_confirm_delete.html"
diff --git a/static/custom_js/place_city_ajax.js b/static/custom_js/place_city_ajax.js
index 716ff370..12cbd744 100644
--- a/static/custom_js/place_city_ajax.js
+++ b/static/custom_js/place_city_ajax.js
@@ -14,6 +14,5 @@
$('#id_city').attr('disabled', false);
});
-
});
});
diff --git a/static/custom_js/wizard.js b/static/custom_js/wizard.js
new file mode 100644
index 00000000..796e2b8f
--- /dev/null
+++ b/static/custom_js/wizard.js
@@ -0,0 +1,167 @@
+/**
+ * Created by dev on 07.09.2015.
+ */
+$(document).ready(function () {
+ $('select').select2({
+ width: 'element',
+ allowClear: true
+ });
+
+ $('#id_country').change(function () {
+ $.get(
+ "/admin/ajax_city/", {'id': $(this).val()}, function (j) {
+
+ $('#id_city').html(j);
+ $('#id_city').attr('disabled', false);
+
+ });
+ });
+ $('#id_place').select2({
+ placeholder:"Место проведения",
+ widht: 400
+ });
+
+ $('#id_city').select2({
+ placeholder: "Город",
+ width: 300,
+ ajax: {
+
+ url: "/admin/city/search/",
+ dataType: "json",
+ quietMillis: 200,
+
+ data: function (term, page, country) {
+ var country = $('#id_country').val()
+ return {
+ term: term,
+ page: page,
+ country: country
+ };
+ },
+
+ results: function (data) {
+ var results = [];
+ $.each(data, function (index, item) {
+ results.push({
+ id: item.id,
+ text: item.label
+ });
+ });
+ return {results: results};
+ }
+ },
+ initSelection: function (element, callback) {
+ var id = $(element).val();
+ var text = $(element).attr('data-init-text');
+ callback({id: id, text: text});
+
+ }
+
+ });
+ $('#id_0-periodic').select2({
+ placeholder: "Периодичность",
+ width: '350px'
+ });
+
+
+ $('#id_tag').select2({
+ placeholder: "Теги",
+ width: '350px',
+ multiple: true,
+ ajax: {
+
+ url: "/admin/theme/tag/search/",
+ dataType: "json",
+ quietMillis: 200,
+ multiple: true,
+
+ data: function (term, page, theme) {
+ var theme = $('#id_theme').serialize().replace(/0-theme/g, 'theme');
+ return {
+ term: term,
+ page: page,
+ theme: theme
+ };
+ },
+
+ results: function (data) {
+ var results = [];
+ $.each(data, function (index, item) {
+ results.push({
+ id: item.id,
+ text: item.label
+ });
+ });
+ return {results: results};
+ }
+ },
+ initSelection: function (element, callback) {
+ var data = [];
+ $(element.val().split(",")).each(function (i) {
+ var item = this.split(':');
+ data.push({
+ id: item[0],
+ text: item[1]
+ });
+ });
+ callback(data);
+
+ }
+
+ });
+ // end selects
+ /*
+ */
+ // theme change
+
+ $('#id_theme').change(function () {
+ $.get(
+ "/admin/ajax_tag/", {'id': $(this).serialize().replace(/0-theme/g, 'theme')}, function (data) {
+ var optionValues = [];
+ var getValues = [];
+ var selectedValues = [];
+ //push values sended from server in array
+ $.each(data, function (i, elem) {
+ getValues.push(elem[0].toString())
+ });
+ //delete options if they aren't in getvalues
+ //otherwise push it in array
+ //also push in array already selected values
+ $('#id_tag option').each(function () {
+ var check = $.inArray($(this), getValues);
+ if ($(this).is(':selected')) {
+ selectedValues.push($(this).val())
+ }
+ if (check == -1) {
+ $(this).remove()
+ }
+ else {
+ optionValues.push($(this).val());
+ }
+ });
+ //generate new options
+ //old options unchanged
+ var html = '';
+ $.each(data, function (i, elem) {
+ var check = $.inArray(elem[0].toString(), optionValues);
+
+ if (check == -1) {
+ html += '';
+ }
+ });
+ $('#id_tag').append(html);
+ //select previous selected values
+ $('#id_tag option').each(function () {
+ var check = $.inArray($(this).val(), selectedValues)
+ if (check != -1) {
+ $(this).attr('selected', 'selected');
+ }
+ });
+ });//end get
+ });//end change
+ console.log("hello from wizard.js");
+ });
\ No newline at end of file
diff --git a/templates/admin/meta/create_seo_text.html b/templates/admin/meta/create_seo_text.html
index a18a44c5..04182684 100644
--- a/templates/admin/meta/create_seo_text.html
+++ b/templates/admin/meta/create_seo_text.html
@@ -41,6 +41,22 @@
{{ form.title.errors }}
+ {# page title #}
+
+
+
+ {{ form.page_title }}
+ {{ form.page_title.errors }}
+
+
+ {# description #}
+
{# body #}
diff --git a/templates/client/blank.html b/templates/client/blank.html
index 1be9b75a..95057c82 100644
--- a/templates/client/blank.html
+++ b/templates/client/blank.html
@@ -21,7 +21,7 @@ This template include basic anf main styles and js files,
- {% include 'includes/meta.html' %}
+ {% include 'client/includes/meta.html' %}
@@ -45,6 +45,9 @@ This template include basic anf main styles and js files,
+ {% block head_scripts %}
+
+ {% endblock %}
{% if request.GET.debug == '1' %}
{% else %}
diff --git a/templates/client/includes/header.html b/templates/client/includes/header.html
index 911ea5a4..69659e51 100644
--- a/templates/client/includes/header.html
+++ b/templates/client/includes/header.html
@@ -11,11 +11,10 @@
+
-
+
-
+
-
-
- {# {% endif %}#}
+
+
{% endblock %}
diff --git a/templates/client/wizard/second_step.html b/templates/client/wizard/second_step.html
index dcd78540..90018852 100644
--- a/templates/client/wizard/second_step.html
+++ b/templates/client/wizard/second_step.html
@@ -1,4 +1,19 @@
{% extends 'client/base_catalog.html' %}
+{% load static %}
+
+
+{% block head_scripts %}
+
+
+{% endblock %}
+
{% block content_list %}
{{ form.errors }}
@@ -51,62 +66,6 @@
-
-
-
-
-
-
-
-
-
-
- {{ form.statistic_year }}
-
-
-
-
-
- {{ form.visitors }}
-
-
-
- {{ form.partisipants }}
-
-
-
- {{ form.square }}
- м²
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Стоимость посещения и участия
diff --git a/wizard/forms.py b/wizard/forms.py
index e77ee6a8..c2e76b1b 100644
--- a/wizard/forms.py
+++ b/wizard/forms.py
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
from django import forms
-from theme.models import Theme, Tag
+from theme.models import Theme
from place_exposition.models import PlaceExposition
-from city.models import City
from country.models import Country
from multiupload.fields import MultiFileField, MultiFileInput
@@ -25,19 +24,19 @@ class ExpoForm1(forms.Form):
date_start = forms.DateField(widget=forms.TextInput(attrs={'class':'data dateFrom', 'placeholder':'дд.мм.гг'}))
date_end = forms.DateField(widget=forms.TextInput(attrs={'class':'data dateTo','placeholder':'дд.мм.гг'}))
- country = forms.ChoiceField(label=u'Страна', choices=[(c.id, c.name) for c in Country.objects.all()])
- theme = forms.MultipleChoiceField(label='Тематики', choices=[(item.id, item.name) for item in Theme.objects.language().all()])
- place = forms.ChoiceField(label=u'Место проведения', required=False, choices=places)
- city = forms.CharField(label=u'Город', widget=forms.HiddenInput())
- tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(), required=False)
+ country = forms.ChoiceField(label=u'Страна', choices=[(c.id, c.name) for c in Country.objects.all()], widget=forms.Select(attrs={'id':'id_country'}))
+ theme = forms.MultipleChoiceField(label='Тематики', choices=[(item.id, item.name) for item in Theme.objects.language().all()], widget=forms.SelectMultiple(attrs={'id':'id_theme'}))
+ place = forms.ChoiceField(label=u'Место проведения', required=False, choices=places, widget=forms.Select(attrs={'id':'id_place'}))
+ city = forms.CharField(label=u'Город', widget=forms.HiddenInput(attrs={'id':'id_city'}))
+ tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(attrs={'id':'id_tag'}), required=False)
audience1 = forms.BooleanField(required=False)
audience2 = forms.BooleanField(required=False)
audience3 = forms.BooleanField(required=False)
- periodic = forms.ChoiceField(choices=choices, required=False, widget=forms.Select(attrs={'placeholder':u'Периодичность'}))
- membership1= forms.BooleanField(required=False)
- membership2= forms.BooleanField(required=False)
- membership3= forms.BooleanField(required=False)
+ periodic = forms.ChoiceField(choices=choices, required=False)
+ membership1 = forms.BooleanField(required=False)
+ membership2 = forms.BooleanField(required=False)
+ membership3 = forms.BooleanField(required=False)
web_site = forms.URLField(required=False, widget=forms.TextInput(attrs={'placeholder': "Веб-сайт (необязательно)"}))
products = forms.CharField(widget=forms.Textarea(attrs={'placeholder': "Экспонируемые продукты", 'cols':30, 'rows':10}))
time_start = forms.TimeField()
@@ -50,12 +49,6 @@ class ExpoForm2(forms.Form):
statistics
"""
found_year = forms.IntegerField()
- statistic_year = forms.IntegerField(widget=forms.TextInput(attrs={'placeholder':'введите год'}))
- visitors = forms.IntegerField(widget=forms.TextInput(attrs={'placeholder':'количество посетителей'}))
- partisipants = forms.IntegerField(widget=forms.TextInput(attrs={'placeholder':'количество учасников'}))
- square = forms.FloatField(widget=forms.TextInput(attrs={'placeholder':'площадь'}))
- countries = forms.ModelChoiceField(queryset=Country.objects.filter(id=50))
-
# ticket price
pre_one_day = forms.FloatField(widget=forms.TextInput(attrs={'placeholder':'на один день'}))
pre_all_days = forms.FloatField(widget=forms.TextInput(attrs={'placeholder':'на все дни'}))
@@ -72,9 +65,11 @@ class ExpoForm2(forms.Form):
class ExpoForm3(forms.Form):
- attachments = MultiFileField(min_num=0, max_num=2, max_file_size=1024*1024*5, widget=MultiFileInput(
- attrs={'class':'button big icon-camera', 'value':u'выберите фотографии', 'id':'files'}
+ """
+ photos from last expositions
+ """
+ attachments = MultiFileField(min_num=0, max_num=6, max_file_size=1024*1024*5, widget=MultiFileInput(
+ attrs={'class':'button big icon-camera', 'value': u'выберите фотографии', 'id': 'files'}
))
-formlist = [ExpoForm1, ExpoForm2, ExpoForm3]
\ No newline at end of file
diff --git a/wizard/urls.py b/wizard/urls.py
index 4ae424d2..527cd96d 100644
--- a/wizard/urls.py
+++ b/wizard/urls.py
@@ -1,8 +1,7 @@
-from django.conf.urls import patterns, url, include
+from django.conf.urls import patterns, url
+from .views import ExpoWizard
+from .forms import ExpoForm1, ExpoForm2,ExpoForm3
-from wizard.views import wizard_view
+formlist = [ExpoForm1,ExpoForm2, ExpoForm3]
-urlpatterns = patterns('',
- # url(r'^ajax/$', 'wizard.views.ajax_view'),
- url(r'^$', wizard_view)
-)
\ No newline at end of file
+urlpatterns = patterns('', url(r'^$', ExpoWizard.as_view(formlist), name = 'add_exposition'))
\ No newline at end of file
diff --git a/wizard/views.py b/wizard/views.py
index 9a9b21ea..01dadcac 100644
--- a/wizard/views.py
+++ b/wizard/views.py
@@ -1,13 +1,27 @@
from django.contrib.formtools.wizard.views import SessionWizardView
from django.core.files.storage import FileSystemStorage
-from django.http import HttpResponseRedirect
+from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.conf import settings
+from django.contrib.auth.decorators import login_required
+from django.utils.decorators import method_decorator
+from django.core.exceptions import PermissionDenied
import os
from photologue.models import Photo
-from exposition.models import Exposition, Statistic
+from exposition.models import Exposition
from functions.form_check import translit_with_separator
from accounts.models import User
+from country.models import Country
+from city.models import City
+from place_exposition.models import PlaceExposition
+from theme.models import Tag, Theme
+
+class LoginRequiredMixin(object):
+ @method_decorator(login_required)
+ def dispatch(self, request, *args, **kwargs):
+ if not request.user.organiser:
+ raise PermissionDenied
+ return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
# defining different template for every form
@@ -17,14 +31,15 @@ TEMPLATES = {
'2': 'client/wizard/third_step.html'
}
-class ExpoWizard(SessionWizardView):
- "main view that handle all data from 3 forms(steps) and finally create an Exposition"
+class ExpoWizard(LoginRequiredMixin, SessionWizardView):
+
+ """main view that handle all data from 3 forms(steps) and finally create an Exposition"""
# storing temporary files during upload
location = os.path.join(settings.MEDIA_ROOT, 'temp')
file_storage = FileSystemStorage(location, settings.MEDIA_URL)
- SUCCES_URL = "/"
+ SUCCESS_URL = "/"
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
@@ -36,16 +51,19 @@ class ExpoWizard(SessionWizardView):
data = self.get_all_cleaned_data()
# creating new exposition
- expo = Exposition.objects.language(self.request.LANGUAGE_CODE).create(
+ lang = self.request.LANGUAGE_CODE
+ expo = Exposition.objects.language(lang).create(
name=data.get('name'),
data_begin=data.get('date_start'),
data_end=data.get('date_end'),
main_title=data.get('main_title'),
description=data.get('description'),
products=data.get('products'),
- country=data.get('country', 1),
- city=data.get('city', 1),
- place=data.get('place', 1),
+
+ country=Country.objects.language(lang).get(id=data.get('country')),
+ city=City.objects.language(lang).get(id=data.get('city')),
+ place=PlaceExposition.objects.language(lang).get(id=data.get('place')),
+
periodic=data.get('periodic'),
web_page=data.get('web_site'),
logo=data.get('logo'),
@@ -66,7 +84,7 @@ class ExpoWizard(SessionWizardView):
url=translit_with_separator(data.get('name')),
quality_label=0,
audience=0,
- creator = User.objects.get(id=self.request.user.id)
+ creator=User.objects.get(id=self.request.user.id)
)
# adding photo to gallery
photos = []
@@ -78,24 +96,13 @@ class ExpoWizard(SessionWizardView):
for photo in photos:
expo.upload_photo(photo)
- # many to many relations saving
- expo.tag = [data.get('tag')]
- expo.theme = [data.get('theme')]
+ expo.tag = Tag.objects.language(lang).filter(id__in=data.get('tag').split(','))
+ expo.theme = Theme.objects.language(lang).filter(id__in=data.get('theme'))
# setting bit fields audience and quality_label
self.set_flags(expo, data)
expo.save()
- # ?
- Statistic.objects.language(self.request.LANGUAGE_CODE).create(
- exposition=expo,
- year=data.get('statistic_year'),
- visitors=data.get('visitors'),
- members=data.get('partisipants'),
- countries=data.get('countries'),
- area=data.get('square')
- )
-
# remove temporary files if it has any
if upload_logo:
self.file_storage.delete(upload_logo.name)
@@ -103,11 +110,10 @@ class ExpoWizard(SessionWizardView):
for f in upload_images:
self.file_storage.delete(f.name)
- return HttpResponseRedirect(self.SUCCES_URL)
-
+ return HttpResponseRedirect(self.SUCCESS_URL)
-
- def set_flags(self, expo, data):
+ @staticmethod
+ def set_flags(expo, data):
if data['membership1']:
expo.quality_label = (expo.quality_label | Exposition.quality_label.exporating)
if data['membership2']:
@@ -122,5 +128,4 @@ class ExpoWizard(SessionWizardView):
if data['audience3']:
expo.audience = expo.audience | (getattr(Exposition.audience, 'general public'))
-from wizard.forms import formlist
-wizard_view = ExpoWizard.as_view(formlist)
+