правки по документу

remotes/origin/stage6
Alexander Burdeinyi 9 years ago
parent 1135ca5741
commit 61a86e9a1d
  1. 6
      accounts/admin.py
  2. 6
      article/models.py
  3. 5
      conference/views.py
  4. 7
      emencia/django/newsletter/forms.py
  5. 4
      emencia/django/newsletter/models.py
  6. 5
      exposition/views.py
  7. 44
      functions/model_mixin.py
  8. 17
      functions/models_methods.py
  9. 15
      functions/pipeline.py
  10. 11
      proj/middleware.py
  11. 1
      requirements.txt
  12. 4
      sortedm2m/__init__.py
  13. 353
      sortedm2m/fields.py
  14. 104
      sortedm2m/forms.py
  15. 0
      sortedm2m/models.py
  16. 7
      sortedm2m/static/sortedm2m/jquery-ui.js
  17. BIN
      sortedm2m/static/sortedm2m/selector-search.gif
  18. 50
      sortedm2m/static/sortedm2m/widget.css
  19. 91
      sortedm2m/static/sortedm2m/widget.js
  20. 23
      sortedm2m/templates/sortedm2m/sorted_checkbox_select_multiple_widget.html
  21. 7
      static/js/select2-4.0.3/js/select2.full.js
  22. 12
      support/d_dev/settings.py
  23. 8
      support/dev/settings.py
  24. 8
      support/prod/settings.py
  25. 23
      templates/c_admin/conference/conference.html
  26. 13
      templates/c_admin/forms/multilang.html
  27. 41
      templates/client/article/news.html
  28. 31
      templates/client/includes/conference/conference_partner.html
  29. 11
      templates/registration/acquire_email.html

@ -9,6 +9,7 @@ from hashlib import md5
from company.models import Company from company.models import Company
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
# from django.contrib import admin
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
@ -30,6 +31,11 @@ from functions.admin_views import AdminListView, AdminView, paginate_results
# models and forms # models and forms
from .models import User from .models import User
#
# class UserAdmin(admin.ModelAdmin):
# search_fields = ['email', ]
# admin.site.register(User, UserAdmin)
class DeleteAccount(DeleteView): class DeleteAccount(DeleteView):
model = User model = User

@ -269,14 +269,14 @@ class Article(TranslatableModel):
tags = self.tag.all().values_list('pk', flat=True) tags = self.tag.all().values_list('pk', flat=True)
themes = self.theme.all().values_list('pk', flat=True) themes = self.theme.all().values_list('pk', flat=True)
exclude_pks = set([self.pk]) exclude_pks = set([self.pk])
qs = model.objects.language() \ qs = model.objects.language()\
.filter(type=self.type, publish_date__isnull=False).order_by('-publish_date') .filter(type=self.type, publish_date__isnull=False).distinct().order_by('-publish_date')
tags_sim = qs.filter(tag__in=tags).exclude(pk__in=exclude_pks)[:4] tags_sim = qs.filter(tag__in=tags).exclude(pk__in=exclude_pks)[:4]
exclude_pks.update([x.pk for x in tags_sim]) exclude_pks.update([x.pk for x in tags_sim])
themes_sim = qs.filter(theme__in=themes).exclude(pk__in=exclude_pks)[:4] themes_sim = qs.filter(theme__in=themes).exclude(pk__in=exclude_pks)[:4]
exclude_pks.update([x.pk for x in themes_sim]) exclude_pks.update([x.pk for x in themes_sim])
last_sim = qs.exclude(pk__in=exclude_pks)[:4] last_sim = qs.exclude(pk__in=exclude_pks)[:4]
result = list(chain(tags_sim, themes_sim, last_sim)[:4]) result = list(chain(tags_sim, themes_sim, last_sim))[:4]
self._similar = result self._similar = result
return self._similar return self._similar

@ -33,7 +33,7 @@ from models import Conference
from note.models import Note from note.models import Note
from service.models import Service from service.models import Service
from service.order_forms import AdvertiseForm from service.order_forms import AdvertiseForm
from service.views import order_forms from service.views import order_forms, get_userlog_data
from stats_collector.mixin import ( from stats_collector.mixin import (
ConfSectionKindMixin, ConfSectionKindMixin,
ConfSectionMixin, ConfSectionMixin,
@ -406,7 +406,8 @@ class ConferenceServiceView(FormMixin, DetailView):
return context return context
def form_valid(self, form): def form_valid(self, form):
order = form.save(commit=False) userlog = get_userlog_data(self.request)
order = form.save(commit=False, userlog=userlog)
order.conference = self.object order.conference = self.object
order.save() order.save()
messages.success(self.request, _(u'Ваш запрос был успешно отправлен')) messages.success(self.request, _(u'Ваш запрос был успешно отправлен'))

@ -12,6 +12,7 @@ from django.utils import translation
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import get_language from django.utils.translation import get_language
from django.utils.encoding import smart_text, force_text from django.utils.encoding import smart_text, force_text
from django.conf import settings
from conference.models import Conference from conference.models import Conference
from exposition.models import Exposition from exposition.models import Exposition
@ -163,6 +164,12 @@ class MailingSettingsForm(forms.ModelForm):
obj.f_countries = self.cleaned_data.get('co') obj.f_countries = self.cleaned_data.get('co')
obj.area = areas obj.area = areas
obj.r_cities = self.cleaned_data.get('r_cities') or [] obj.r_cities = self.cleaned_data.get('r_cities') or []
if obj.moscow and not settings.MOSCOW_PK in obj.r_cities:
obj.r_cities.add(settings.MOSCOW_PK)
if not obj.moscow and settings.MOSCOW_PK in obj.r_cities:
obj.moscow = True
obj.tags = self.cleaned_data.get('tg') or [] obj.tags = self.cleaned_data.get('tg') or []
obj.themes = self.cleaned_data.get('th') or [] obj.themes = self.cleaned_data.get('th') or []
obj.from_users = False obj.from_users = False

@ -164,8 +164,8 @@ class Contact(models.Model):
periodic_day = models.PositiveSmallIntegerField(_(u'День отправки'), periodic_day = models.PositiveSmallIntegerField(_(u'День отправки'),
choices=PERIODIC_DAY_CHOICES, default=PERIODIC_DAY_CHOICES.WED) choices=PERIODIC_DAY_CHOICES, default=PERIODIC_DAY_CHOICES.WED)
content_news = models.BooleanField(_(u'Новости событий'), blank=True, default=True) content_news = models.BooleanField(_(u'Новости событий'), blank=True, default=True)
content_overview = models.BooleanField(_(u'Обзоры'), blank=True, default=True) content_overview = models.BooleanField(_(u'Статьи для экспонентов'), blank=True, default=True)
content_articles = models.BooleanField(_(u'Статьи из блога по участию в вывставках'), blank=True, default=True) content_articles = models.BooleanField(_(u'Статьи для организаторов событий'), blank=True, default=True)
tags = models.ManyToManyField('theme.Tag', verbose_name=_(u'Теги'), blank=True, null=True) tags = models.ManyToManyField('theme.Tag', verbose_name=_(u'Теги'), blank=True, null=True)
themes = models.ManyToManyField('theme.Theme', blank=True, null=True, verbose_name=_(u'Тематики')) themes = models.ManyToManyField('theme.Theme', blank=True, null=True, verbose_name=_(u'Тематики'))

@ -32,7 +32,7 @@ from models import Exposition
from note.models import Note from note.models import Note
from service.models import Service from service.models import Service
from service.order_forms import AdvertiseForm from service.order_forms import AdvertiseForm
from service.views import order_forms from service.views import order_forms, get_userlog_data
# from stats_collector.models import SectionStats # from stats_collector.models import SectionStats
from stats_collector.mixin import ( from stats_collector.mixin import (
ExpoSectionKindMixin, ExpoSectionKindMixin,
@ -327,7 +327,8 @@ class ExpositionServiceView(JitterCacheMixin, MetadataMixin, FormMixin, DetailVi
return context return context
def form_valid(self, form): def form_valid(self, form):
order = form.save(commit=False) userlog = get_userlog_data(self.request)
order = form.save(commit=False, userlog=userlog)
order.exposition = self.object order.exposition = self.object
order.save() order.save()
return HttpResponseRedirect(self.object.get_permanent_url()+'service/thanks/') return HttpResponseRedirect(self.object.get_permanent_url()+'service/thanks/')

@ -114,29 +114,39 @@ class EventMixin(object):
} }
return ctx return ctx
def get_nearest_events_incl(self, _qs, tags, themes, exclude=None):
now = datetime.datetime.now()
month = now + relativedelta(months=1)
month2 = now + relativedelta(months=2)
exclude_pks = exclude or set([self.pk])
events_m2 = []
events_m = []
events = []
for params in [{'tag__in': tags}, {'theme__in': themes}]:
qs = _qs.filter(**params).order_by('data_begin')
events_m2.extend(qs.filter(data_begin__gte=month2).exclude(pk__in=exclude_pks)[:3])
exclude_pks.update([x.pk for x in events_m2])
events_m.extend(qs.filter(data_begin__gte=month).exclude(pk__in=exclude_pks)[:3])
exclude_pks.update([x.pk for x in events_m])
events.extend(qs.filter(data_begin__gte=now).exclude(pk__in=exclude_pks)[:3])
exclude_pks.update([x.pk for x in events])
return (list(
sorted((chain(zip(*[x for x in [events_m2, events_m, events] if x]))[:3]), key=lambda x: x.data_begin)),
exclude_pks)
def get_nearest_events(self): def get_nearest_events(self):
if getattr(self, '_nearest_events', None) is None: if getattr(self, '_nearest_events', None) is None:
model = self.__class__ model = self.__class__
result = [] result = []
tags = self.tag.all().values_list('pk', flat=True) tags = self.tag.all().values_list('pk', flat=True)
themes = self.theme.all().values_list('pk', flat=True) themes = self.theme.all().values_list('pk', flat=True)
now = datetime.datetime.now() qs = model.objects.language().filter(country_id=self.country_id)
month = now + relativedelta(months=1) result, exclude = self.get_nearest_events_incl(qs, tags, themes)
month2 = now + relativedelta(months=2) if len(result) > 3:
exclude_pks = set([self.pk]) qs = model.objects.language()
events_m2 = [] r, e = self.get_nearest_events_incl(qs, tags, themes, exclude)
events_m = [] result += r
events = [] self._nearest_events = result[:3]
for params in [{'tag__in': tags}, {'theme__in': themes}]:
qs = model.objects.language().filter(**params).order_by('data_begin')
events_m2.extend(qs.filter(data_begin__gte=month2).exclude(pk__in=exclude_pks)[:3])
exclude_pks.update([x.pk for x in events_m2])
events_m.extend(qs.filter(data_begin__gte=month).exclude(pk__in=exclude_pks)[:3])
exclude_pks.update([x.pk for x in events_m])
events.extend(qs.filter(data_begin__gte=now).exclude(pk__in=exclude_pks)[:3])
exclude_pks.update([x.pk for x in events])
result = list(sorted((chain(zip(*[x for x in [events_m2, events_m, events] if x]))[:3]), key=lambda x: x.data_begin))
self._nearest_events = result
return self._nearest_events return self._nearest_events
def get_nearest_events_url(self): def get_nearest_events_url(self):

@ -192,12 +192,21 @@ class CityManager(TranslationManager):
if cached and key in cache: if cached and key in cache:
cities = cache.get(key) cities = cache.get(key)
else: else:
cities = list( cities = []
self.language(lang).filter( popular_cities = []
_cities = self.language(lang).filter(
country__url='russia', exposition_city__isnull=False, country__url='russia', exposition_city__isnull=False,
conference_city__isnull=False conference_city__isnull=False
).exclude(pk=settings.MOSCOW_PK).distinct().order_by('name').values_list('pk', 'name') ).distinct().order_by('name').values_list('pk', 'name')
) for city in _cities:
if city[0] == settings.MOSCOW_PK:
popular_cities.insert(0, city)
elif city[0] == settings.SPB_PK:
popular_cities.append(city)
else:
cities.append(city)
# .exclude(pk=settings.MOSCOW_PK)
cities = popular_cities + cities
cache.set(key, cities, self.cache_time) cache.set(key, cities, self.cache_time)
return cities return cities

@ -78,6 +78,21 @@ def require_email(strategy, details, user=None, is_new=False, *args, **kwargs):
return return
def social_user(backend, uid, user=None, *args, **kwargs):
provider = backend.name
social = backend.strategy.storage.user.get_social_auth(provider, uid)
if social:
# if user and social.user != user:
# msg = 'This {0} account is already in use.'.format(provider)
# raise AuthAlreadyAssociated(backend, msg)
# elif not user:
user = social.user
return {'social': social,
'user': user,
'is_new': user is None,
'new_association': social is None}
def SendVerificationEmail(strategy, backend, code): def SendVerificationEmail(strategy, backend, code):
""" """
Send an email with an embedded verification code and the necessary details to restore the required session Send an email with an embedded verification code and the necessary details to restore the required session

@ -54,12 +54,17 @@ class Referer(object):
for key, val in data_exists.iteritems(): for key, val in data_exists.iteritems():
if val: if val:
if key == 'search': if key == 'search':
print(request.session.get('search', []))
print(request.session.get('search', []))[-2:]
search = request.session.get('search', [])[-2:] search = request.session.get('search', [])[-2:]
search.append(val) search.append(val)
request.session['search'] = search request.session['search'] = search
if userlog is not None: try:
for i, d in enumerate(search, start=1): if userlog is not None:
setattr(userlog, key + str(i), d) for i, d in enumerate(search, start=1):
setattr(userlog, key + str(i), d)
except Exception as e:
print(e)
else: else:
attr1 = key + '1' attr1 = key + '1'
attr2 = key + '2' attr2 = key + '2'

@ -17,6 +17,7 @@ django-redis==4.0.0
django-redis-cache==0.13.1 django-redis-cache==0.13.1
django-sortedm2m==1.2.0 django-sortedm2m==1.2.0
django-tinymce==2.0.5 django-tinymce==2.0.5
django-widget-tweaks==1.4.1
djutils==0.3.2 djutils==0.3.2
docutils==0.12 docutils==0.12
fpconst==0.7.2 fpconst==0.7.2

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
__version__ = '0.7.0'

@ -0,0 +1,353 @@
# -*- coding: utf-8 -*-
from operator import attrgetter
import sys
from django.db import connections
from django.db import router
from django.db.models import signals
from django.db.models.fields.related import add_lazy_relation, create_many_related_manager
from django.db.models.fields.related import ManyToManyField, ReverseManyRelatedObjectsDescriptor
from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT
from django.conf import settings
from django.utils.functional import curry
from sortedm2m.forms import SortedMultipleChoiceField
if sys.version_info[0] < 3:
string_types = basestring
else:
string_types = str
SORT_VALUE_FIELD_NAME = 'sort_value'
def create_sorted_many_to_many_intermediate_model(field, klass):
from django.db import models
managed = True
if isinstance(field.rel.to, string_types) and field.rel.to != RECURSIVE_RELATIONSHIP_CONSTANT:
to_model = field.rel.to
to = to_model.split('.')[-1]
def set_managed(field, model, cls):
field.rel.through._meta.managed = model._meta.managed or cls._meta.managed
add_lazy_relation(klass, field, to_model, set_managed)
elif isinstance(field.rel.to, string_types):
to = klass._meta.object_name
to_model = klass
managed = klass._meta.managed
else:
to = field.rel.to._meta.object_name
to_model = field.rel.to
managed = klass._meta.managed or to_model._meta.managed
name = '%s_%s' % (klass._meta.object_name, field.name)
if field.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT or to == klass._meta.object_name:
from_ = 'from_%s' % to.lower()
to = 'to_%s' % to.lower()
else:
from_ = klass._meta.object_name.lower()
to = to.lower()
meta = type(str('Meta'), (object,), {
'db_table': field._get_m2m_db_table(klass._meta),
'managed': managed,
'auto_created': klass,
'app_label': klass._meta.app_label,
'unique_together': (from_, to),
'ordering': (field.sort_value_field_name,),
'verbose_name': '%(from)s-%(to)s relationship' % {'from': from_, 'to': to},
'verbose_name_plural': '%(from)s-%(to)s relationships' % {'from': from_, 'to': to},
})
# Construct and return the new class.
def default_sort_value(name):
model = models.get_model(klass._meta.app_label, name)
return model._default_manager.count()
default_sort_value = curry(default_sort_value, name)
return type(str(name), (models.Model,), {
'Meta': meta,
'__module__': klass.__module__,
from_: models.ForeignKey(klass, related_name='%s+' % name),
to: models.ForeignKey(to_model, related_name='%s+' % name),
field.sort_value_field_name: models.IntegerField(default=default_sort_value),
'_sort_field_name': field.sort_value_field_name,
'_from_field_name': from_,
'_to_field_name': to,
})
def create_sorted_many_related_manager(superclass, rel):
RelatedManager = create_many_related_manager(superclass, rel)
class SortedRelatedManager(RelatedManager):
def get_query_set(self):
# We use ``extra`` method here because we have no other access to
# the extra sorting field of the intermediary model. The fields
# are hidden for joins because we set ``auto_created`` on the
# intermediary's meta options.
try:
return self.instance._prefetched_objects_cache[self.prefetch_cache_name]
except (AttributeError, KeyError):
return super(SortedRelatedManager, self).\
get_query_set().\
extra(order_by=['%s.%s' % (
rel.through._meta.db_table,
rel.through._sort_field_name,
)])
if not hasattr(RelatedManager, '_get_fk_val'):
@property
def _fk_val(self):
return self._pk_val
def get_prefetch_query_set(self, instances):
# mostly a copy of get_prefetch_query_set from ManyRelatedManager
# but with addition of proper ordering
db = self._db or router.db_for_read(instances[0].__class__, instance=instances[0])
query = {'%s__pk__in' % self.query_field_name:
set(obj._get_pk_val() for obj in instances)}
qs = super(RelatedManager, self).get_query_set().using(db)._next_is_sticky().filter(**query)
# M2M: need to annotate the query in order to get the primary model
# that the secondary model was actually related to. We know that
# there will already be a join on the join table, so we can just add
# the select.
# For non-autocreated 'through' models, can't assume we are
# dealing with PK values.
fk = self.through._meta.get_field(self.source_field_name)
source_col = fk.column
join_table = self.through._meta.db_table
connection = connections[db]
qn = connection.ops.quote_name
qs = qs.extra(select={'_prefetch_related_val':
'%s.%s' % (qn(join_table), qn(source_col))},
order_by=['%s.%s' % (
rel.through._meta.db_table,
rel.through._sort_field_name,
)])
select_attname = fk.rel.get_related_field().get_attname()
return (qs,
attrgetter('_prefetch_related_val'),
attrgetter(select_attname),
False,
self.prefetch_cache_name)
def _add_items(self, source_field_name, target_field_name, *objs):
# source_field_name: the PK fieldname in join_table for the source object
# target_field_name: the PK fieldname in join_table for the target object
# *objs - objects to add. Either object instances, or primary keys of object instances.
# If there aren't any objects, there is nothing to do.
from django.db.models import Model
if objs:
new_ids = []
for obj in objs:
if isinstance(obj, self.model):
if not router.allow_relation(obj, self.instance):
raise ValueError('Cannot add "%r": instance is on database "%s", value is on database "%s"' %
(obj, self.instance._state.db, obj._state.db))
if hasattr(self, '_get_fk_val'): # Django>=1.5
fk_val = self._get_fk_val(obj, target_field_name)
if fk_val is None:
raise ValueError('Cannot add "%r": the value for field "%s" is None' %
(obj, target_field_name))
new_ids.append(self._get_fk_val(obj, target_field_name))
else: # Django<1.5
new_ids.append(obj.pk)
elif isinstance(obj, Model):
raise TypeError("'%s' instance expected, got %r" % (self.model._meta.object_name, obj))
else:
new_ids.append(obj)
db = router.db_for_write(self.through, instance=self.instance)
vals = self.through._default_manager.using(db).values_list(target_field_name, flat=True)
vals = vals.filter(**{
source_field_name: self._fk_val,
'%s__in' % target_field_name: new_ids,
})
for val in vals:
if val in new_ids:
new_ids.remove(val)
_new_ids = []
for pk in new_ids:
if pk not in _new_ids:
_new_ids.append(pk)
new_ids = _new_ids
new_ids_set = set(new_ids)
if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are inserting the
# duplicate data row for symmetrical reverse entries.
signals.m2m_changed.send(sender=rel.through, action='pre_add',
instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=new_ids_set, using=db)
# Add the ones that aren't there already
sort_field_name = self.through._sort_field_name
sort_field = self.through._meta.get_field_by_name(sort_field_name)[0]
for obj_id in new_ids:
self.through._default_manager.using(db).create(**{
'%s_id' % source_field_name: self._fk_val, # Django 1.5 compatibility
'%s_id' % target_field_name: obj_id,
sort_field_name: sort_field.get_default(),
})
if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are inserting the
# duplicate data row for symmetrical reverse entries.
signals.m2m_changed.send(sender=rel.through, action='post_add',
instance=self.instance, reverse=self.reverse,
model=self.model, pk_set=new_ids_set, using=db)
return SortedRelatedManager
class ReverseSortedManyRelatedObjectsDescriptor(ReverseManyRelatedObjectsDescriptor):
@property
def related_manager_cls(self):
return create_sorted_many_related_manager(
self.field.rel.to._default_manager.__class__,
self.field.rel
)
class SortedManyToManyField(ManyToManyField):
'''
Providing a many to many relation that remembers the order of related
objects.
Accept a boolean ``sorted`` attribute which specifies if relation is
ordered or not. Default is set to ``True``. If ``sorted`` is set to
``False`` the field will behave exactly like django's ``ManyToManyField``.
'''
def __init__(self, to, sorted=True, **kwargs):
self.sorted = sorted
self.sort_value_field_name = kwargs.pop(
'sort_value_field_name',
SORT_VALUE_FIELD_NAME)
super(SortedManyToManyField, self).__init__(to, **kwargs)
if self.sorted:
self.help_text = kwargs.get('help_text', None)
def contribute_to_class(self, cls, name):
if not self.sorted:
return super(SortedManyToManyField, self).contribute_to_class(cls, name)
# To support multiple relations to self, it's useful to have a non-None
# related name on symmetrical relations for internal reasons. The
# concept doesn't make a lot of sense externally ("you want me to
# specify *what* on my non-reversible relation?!"), so we set it up
# automatically. The funky name reduces the chance of an accidental
# clash.
if self.rel.symmetrical and (self.rel.to == "self" or self.rel.to == cls._meta.object_name):
self.rel.related_name = "%s_rel_+" % name
super(ManyToManyField, self).contribute_to_class(cls, name)
# The intermediate m2m model is not auto created if:
# 1) There is a manually specified intermediate, or
# 2) The class owning the m2m field is abstract.
if not self.rel.through and not cls._meta.abstract:
self.rel.through = create_sorted_many_to_many_intermediate_model(self, cls)
# Add the descriptor for the m2m relation
setattr(cls, self.name, ReverseSortedManyRelatedObjectsDescriptor(self))
# Set up the accessor for the m2m table name for the relation
self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta)
# Populate some necessary rel arguments so that cross-app relations
# work correctly.
if isinstance(self.rel.through, string_types):
def resolve_through_model(field, model, cls):
field.rel.through = model
add_lazy_relation(cls, self, self.rel.through, resolve_through_model)
if hasattr(cls._meta, 'duplicate_targets'): # Django<1.5
if isinstance(self.rel.to, string_types):
target = self.rel.to
else:
target = self.rel.to._meta.db_table
cls._meta.duplicate_targets[self.column] = (target, "m2m")
def formfield(self, **kwargs):
defaults = {}
if self.sorted:
defaults['form_class'] = SortedMultipleChoiceField
defaults.update(kwargs)
return super(SortedManyToManyField, self).formfield(**defaults)
# Add introspection rules for South database migrations
# See http://south.aeracode.org/docs/customfields.html
try:
import south
except ImportError:
south = None
if south is not None and 'south' in settings.INSTALLED_APPS:
from south.modelsinspector import add_introspection_rules
add_introspection_rules(
[(
(SortedManyToManyField,),
[],
{"sorted": ["sorted", {"default": True}]},
)],
[r'^sortedm2m\.fields\.SortedManyToManyField']
)
# Monkeypatch South M2M actions to create the sorted through model.
# FIXME: This doesn't detect if you changed the sorted argument to the field.
import south.creator.actions
from south.creator.freezer import model_key
class AddM2M(south.creator.actions.AddM2M):
SORTED_FORWARDS_TEMPLATE = '''
# Adding SortedM2M table for field %(field_name)s on '%(model_name)s'
db.create_table(%(table_name)r, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
(%(left_field)r, models.ForeignKey(orm[%(left_model_key)r], null=False)),
(%(right_field)r, models.ForeignKey(orm[%(right_model_key)r], null=False)),
(%(sort_field)r, models.IntegerField())
))
db.create_unique(%(table_name)r, [%(left_column)r, %(right_column)r])'''
def console_line(self):
if isinstance(self.field, SortedManyToManyField) and self.field.sorted:
return " + Added SortedM2M table for %s on %s.%s" % (
self.field.name,
self.model._meta.app_label,
self.model._meta.object_name,
)
else:
return super(AddM2M, self).console_line()
def forwards_code(self):
if isinstance(self.field, SortedManyToManyField) and self.field.sorted:
return self.SORTED_FORWARDS_TEMPLATE % {
"model_name": self.model._meta.object_name,
"field_name": self.field.name,
"table_name": self.field.m2m_db_table(),
"left_field": self.field.m2m_column_name()[:-3], # Remove the _id part
"left_column": self.field.m2m_column_name(),
"left_model_key": model_key(self.model),
"right_field": self.field.m2m_reverse_name()[:-3], # Remove the _id part
"right_column": self.field.m2m_reverse_name(),
"right_model_key": model_key(self.field.rel.to),
"sort_field": self.field.sort_value_field_name,
}
else:
return super(AddM2M, self).forwards_code()
class DeleteM2M(AddM2M):
def console_line(self):
return " - Deleted M2M table for %s on %s.%s" % (
self.field.name,
self.model._meta.app_label,
self.model._meta.object_name,
)
def forwards_code(self):
return AddM2M.backwards_code(self)
def backwards_code(self):
return AddM2M.forwards_code(self)
south.creator.actions.AddM2M = AddM2M
south.creator.actions.DeleteM2M = DeleteM2M

@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
import sys
from itertools import chain
from django import forms
from django.conf import settings
from django.db.models.query import QuerySet
from django.template.loader import render_to_string
from django.utils.encoding import force_text
from django.utils.html import conditional_escape, escape
from django.utils.safestring import mark_safe
if sys.version_info[0] < 3:
iteritems = lambda d: iter(d.iteritems())
string_types = basestring,
str_ = unicode
else:
iteritems = lambda d: iter(d.items())
string_types = str,
str_ = str
STATIC_URL = getattr(settings, 'STATIC_URL', settings.MEDIA_URL)
class SortedCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
class Media:
js = (
STATIC_URL + 'sortedm2m/widget.js',
STATIC_URL + 'sortedm2m/jquery-ui.js',
)
css = {'screen': (
STATIC_URL + 'sortedm2m/widget.css',
)}
def build_attrs(self, attrs=None, **kwargs):
attrs = super(SortedCheckboxSelectMultiple, self).\
build_attrs(attrs, **kwargs)
classes = attrs.setdefault('class', '').split()
classes.append('sortedm2m')
attrs['class'] = ' '.join(classes)
return attrs
def render(self, name, value, attrs=None, choices=()):
if value is None: value = []
has_id = attrs and 'id' in attrs
final_attrs = self.build_attrs(attrs, name=name)
# Normalize to strings
str_values = [force_text(v) for v in value]
selected = []
unselected = []
for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
# If an ID attribute was given, add a numeric index as a suffix,
# so that the checkboxes don't all have the same ID attribute.
if has_id:
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
label_for = ' for="%s"' % conditional_escape(final_attrs['id'])
else:
label_for = ''
cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
option_value = force_text(option_value)
rendered_cb = cb.render(name, option_value)
option_label = conditional_escape(force_text(option_label))
item = {'label_for': label_for, 'rendered_cb': rendered_cb, 'option_label': option_label, 'option_value': option_value}
if option_value in str_values:
selected.append(item)
else:
unselected.append(item)
# re-order `selected` array according str_values which is a set of `option_value`s in the order they should be shown on screen
ordered = []
for value in str_values:
for select in selected:
if value == select['option_value']:
ordered.append(select)
selected = ordered
html = render_to_string(
'sortedm2m/sorted_checkbox_select_multiple_widget.html',
{'selected': selected, 'unselected': unselected})
return mark_safe(html)
def value_from_datadict(self, data, files, name):
value = data.get(name, None)
if isinstance(value, string_types):
return [v for v in value.split(',') if v]
return value
class SortedMultipleChoiceField(forms.ModelMultipleChoiceField):
widget = SortedCheckboxSelectMultiple
def clean(self, value):
queryset = super(SortedMultipleChoiceField, self).clean(value)
if value is None or not isinstance(queryset, QuerySet):
return queryset
object_list = dict((
(str_(key), value)
for key, value in iteritems(queryset.in_bulk(value))))
return [object_list[str_(pk)] for pk in value]

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

@ -0,0 +1,50 @@
.sortedm2m-container {
margin-right: 10px;
width: 570px;
}
.sortedm2m-container p.selector-filter {
width: 570px;
padding: 0;
margin: 0;
}
.sortedm2m-container p.selector-filter input {
width: 532px;
margin: 5px 4px;
}
ul.sortedm2m {
display: block;
width: 554px;
min-height: 200px;
max-height: 400px;
overflow-x: hidden;
overflow-y: auto;
margin: 0;
padding: 6px 8px;
list-style-type: none;
text-align: left;
}
ul.sortedm2m li {
list-style-type: none;
text-align: left;
width: 550px;
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
}
ul.sortedm2m li, ul.sortedm2m label {
cursor: move;
}
/* required to work properly in django admin */
body.change-form .sortedm2m-container {
float: left;
}
.module ul.sortedm2m {
margin: 0;
padding: 6px 8px;
}

@ -0,0 +1,91 @@
if (jQuery === undefined) {
jQuery = django.jQuery;
}
(function ($) {
$(function () {
$('.sortedm2m').parents('ul').each(function () {
$(this).addClass('sortedm2m');
var checkboxes = $(this).find('input[type=checkbox]');
var id = checkboxes.first().attr('id').match(/^(.*)_\d+$/)[1];
var name = checkboxes.first().attr('name');
checkboxes.removeAttr('name');
$(this).before('<input type="hidden" id="' + id + '" name="' + name + '" />');
var that = this;
var recalculate_value = function () {
var values = [];
$(that).find(':checked').each(function () {
values.push($(this).val());
});
$('#' + id).val(values.join(','));
}
recalculate_value();
checkboxes.change(recalculate_value);
$(this).sortable({
axis: 'y',
//containment: 'parent',
update: recalculate_value
});
});
$('.sortedm2m-container .selector-filter input').each(function () {
$(this).bind('input', function() {
var search = $(this).val().toLowerCase();
var $el = $(this).closest('.selector-filter');
var $container = $el.siblings('ul').each(function() {
// walk over each child list el and do name comparisons
$(this).children().each(function() {
var curr = $(this).find('label').text().toLowerCase();
if (curr.indexOf(search) === -1) {
$(this).css('display', 'none');
} else {
$(this).css('display', 'inherit');
};
});
});
});
});
if (window.showAddAnotherPopup) {
var django_dismissAddAnotherPopup = window.dismissAddAnotherPopup;
window.dismissAddAnotherPopup = function (win, newId, newRepr) {
// newId and newRepr are expected to have previously been escaped by
// django.utils.html.escape.
newId = html_unescape(newId);
newRepr = html_unescape(newRepr);
var name = windowname_to_id(win.name);
var elem = $('#' + name);
var sortedm2m = elem.siblings('ul.sortedm2m');
if (sortedm2m.length == 0) {
// no sortedm2m widget, fall back to django's default
// behaviour
return django_dismissAddAnotherPopup.apply(this, arguments);
}
if (elem.val().length > 0) {
elem.val(elem.val() + ',');
}
elem.val(elem.val() + newId);
var id_template = '';
var maxid = 0;
sortedm2m.find('li input').each(function () {
var match = this.id.match(/^(.+)_(\d+)$/);
id_template = match[1];
id = parseInt(match[2]);
if (id > maxid) maxid = id;
});
var id = id_template + '_' + (maxid + 1);
var new_li = $('<li/>').append(
$('<label/>').attr('for', id).append(
$('<input class="sortedm2m" type="checkbox" checked="checked" />').attr('id', id).val(newId)
).append($('<span/>').text(' ' + newRepr))
);
sortedm2m.append(new_li);
win.close();
};
}
});
})(jQuery);

@ -0,0 +1,23 @@
{% load i18n static %}
<div class="sortedm2m-container">
<p class="selector-filter">
<img src="{% static "sortedm2m/selector-search.gif" %}" alt="" title="{% trans "Type into this box to filter down the list." %}" />
<input type="text" placeholder="{% trans "Filter" %}" />
</p>
<ul>
{% for row in selected %}
<li><label{{ row.label_for|safe }}>{{ row.rendered_cb }} {{ row.option_label }}</label></li>
{% endfor %}
{% for row in unselected %}
<li><label{{ row.label_for|safe }}>{{ row.rendered_cb }} {{ row.option_label }}</label></li>
{% endfor %}
</ul>
<p class="help">
{% trans "Choose items and order by drag & drop." %}
</p>
</div>

@ -1,3 +1,10 @@
/*!
* Select2 4.0.3
* https://select2.github.io
*
* Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md
*/
/*! /*!
* Select2 4.0.3 * Select2 4.0.3
* https://select2.github.io * https://select2.github.io

@ -154,10 +154,11 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'social.apps.django_app.middleware.SocialAuthExceptionMiddleware', 'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
# 'django.middleware.cache.FetchFromCacheMiddleware', # 'django.middleware.cache.FetchFromCacheMiddleware',
# Uncomment the next line for simple clickjacking protection:
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'proj.middleware.Referer',
'django.contrib.redirects.middleware.RedirectFallbackMiddleware', 'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
'proj.middleware.ExpoRedirectFallbackMiddleware', 'proj.middleware.ExpoRedirectFallbackMiddleware',
'proj.middleware.SpacelessMiddleware',
) )
@ -259,9 +260,12 @@ SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
SOCIAL_AUTH_PIPELINE = ( SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details', 'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid', 'social.pipeline.social_auth.social_uid',
'functions.pipeline.get_email', # vk
'functions.pipeline.load_user', 'functions.pipeline.load_user',
'social.pipeline.social_auth.auth_allowed', 'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user', 'functions.pipeline.social_user',
# 'social.pipeline.social_auth.social_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.get_username', 'social.pipeline.user.get_username',
'functions.pipeline.require_email', 'functions.pipeline.require_email',
#'social.pipeline.mail.mail_validation', #'social.pipeline.mail.mail_validation',
@ -269,7 +273,6 @@ SOCIAL_AUTH_PIPELINE = (
#'social.pipeline.user.create_user', #'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_by_email', 'social.pipeline.social_auth.associate_by_email',
'social.pipeline.social_auth.associate_user', 'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details' 'social.pipeline.user.user_details'
) )
@ -377,6 +380,8 @@ INSTALLED_APPS = (
'specialist_catalog', 'specialist_catalog',
'south', 'south',
'rosetta', 'rosetta',
'widget_tweaks',
) )
CRONJOBS = [ CRONJOBS = [
@ -499,6 +504,7 @@ MONTHES = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2,
SNG_COUNTRIES = [159, 186, 31, 6, 99, 13, 189, 64] SNG_COUNTRIES = [159, 186, 31, 6, 99, 13, 189, 64]
RUSSIA_PK = 159 RUSSIA_PK = 159
MOSCOW_PK = -2960561 MOSCOW_PK = -2960561
SPB_PK = -2996338
CLIENT_DATE_FORMAT = ["%d.%m.%Y"] CLIENT_DATE_FORMAT = ["%d.%m.%Y"]

@ -151,8 +151,8 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'social.apps.django_app.middleware.SocialAuthExceptionMiddleware', 'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
# 'django.middleware.cache.FetchFromCacheMiddleware', # 'django.middleware.cache.FetchFromCacheMiddleware',
# Uncomment the next line for simple clickjacking protection:
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'proj.middleware.Referer',
'django.contrib.redirects.middleware.RedirectFallbackMiddleware', 'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
'proj.middleware.ExpoRedirectFallbackMiddleware', 'proj.middleware.ExpoRedirectFallbackMiddleware',
'proj.middleware.SpacelessMiddleware', 'proj.middleware.SpacelessMiddleware',
@ -260,7 +260,8 @@ SOCIAL_AUTH_PIPELINE = (
'functions.pipeline.get_email', # vk 'functions.pipeline.get_email', # vk
'functions.pipeline.load_user', 'functions.pipeline.load_user',
'social.pipeline.social_auth.auth_allowed', 'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user', 'functions.pipeline.social_user',
# 'social.pipeline.social_auth.social_user',
'social.pipeline.social_auth.load_extra_data', 'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.get_username', 'social.pipeline.user.get_username',
'functions.pipeline.require_email', 'functions.pipeline.require_email',
@ -378,6 +379,8 @@ INSTALLED_APPS = (
'specialist_catalog', 'specialist_catalog',
'south', 'south',
'rosetta', 'rosetta',
'widget_tweaks',
) )
CRONJOBS = [ CRONJOBS = [
@ -501,6 +504,7 @@ MONTHES = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2,
SNG_COUNTRIES = [159, 186, 31, 6, 99, 13, 189, 64] SNG_COUNTRIES = [159, 186, 31, 6, 99, 13, 189, 64]
RUSSIA_PK = 159 RUSSIA_PK = 159
MOSCOW_PK = -2960561 MOSCOW_PK = -2960561
SPB_PK = -2996338
CLIENT_DATE_FORMAT = ["%d.%m.%Y"] CLIENT_DATE_FORMAT = ["%d.%m.%Y"]

@ -151,8 +151,8 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'social.apps.django_app.middleware.SocialAuthExceptionMiddleware', 'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
# 'django.middleware.cache.FetchFromCacheMiddleware', # 'django.middleware.cache.FetchFromCacheMiddleware',
# Uncomment the next line for simple clickjacking protection:
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'proj.middleware.Referer',
'django.contrib.redirects.middleware.RedirectFallbackMiddleware', 'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
'proj.middleware.ExpoRedirectFallbackMiddleware', 'proj.middleware.ExpoRedirectFallbackMiddleware',
'proj.middleware.SpacelessMiddleware', 'proj.middleware.SpacelessMiddleware',
@ -260,7 +260,8 @@ SOCIAL_AUTH_PIPELINE = (
'functions.pipeline.get_email', # vk 'functions.pipeline.get_email', # vk
'functions.pipeline.load_user', 'functions.pipeline.load_user',
'social.pipeline.social_auth.auth_allowed', 'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user', 'functions.pipeline.social_user',
# 'social.pipeline.social_auth.social_user',
'social.pipeline.social_auth.load_extra_data', 'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.get_username', 'social.pipeline.user.get_username',
'functions.pipeline.require_email', 'functions.pipeline.require_email',
@ -378,6 +379,8 @@ INSTALLED_APPS = (
'specialist_catalog', 'specialist_catalog',
'south', 'south',
'rosetta', 'rosetta',
'widget_tweaks',
) )
CRONJOBS = [ CRONJOBS = [
@ -500,6 +503,7 @@ MONTHES = {'jan': {'value': 1, 'name': _(u'Январь')}, 'feb': {'value': 2,
SNG_COUNTRIES = [159, 186, 31, 6, 99, 13, 189, 64] SNG_COUNTRIES = [159, 186, 31, 6, 99, 13, 189, 64]
RUSSIA_PK = 159 RUSSIA_PK = 159
MOSCOW_PK = -2960561 MOSCOW_PK = -2960561
SPB_PK = -2996338
CLIENT_DATE_FORMAT = ["%d.%m.%Y"] CLIENT_DATE_FORMAT = ["%d.%m.%Y"]

@ -109,7 +109,13 @@
{# return undefined;#} {# return undefined;#}
{# },#} {# },#}
}); });
{##}
{# $('#id_tag, #id_theme, #id_city, #id_country, #id_place_conference').on('select2-open', function () {#}
{# $('#id_audience').prop("disabled", true);#}
{# });#}
{# $('#id_tag, #id_theme, #id_city, #id_country, #id_place_conference').on('select2-close', function () {#}
{# $('#id_audience').prop("disabled", false);#}
{# });#}
}); });
</script> </script>
@ -151,7 +157,13 @@
<span class="help-inline">{{ form.data_end.errors }}</span> <span class="help-inline">{{ form.data_end.errors }}</span>
</div> </div>
</div> </div>
{# audience #}
<div class="control-group {% if form.audience.errors %}error{% endif %}">
<label class="control-label">{{ form.audience.label }}:</label>
<div class="controls">{{ form.audience }}
<span class="help-inline">{{ form.audience.errors }}</span>
</div>
</div>
{# country #} {# country #}
<div class="control-group {% if form.country.errors %}error{% endif %}"> <div class="control-group {% if form.country.errors %}error{% endif %}">
<label class="control-label"><b>{{ form.country.label }}:</b></label> <label class="control-label"><b>{{ form.country.label }}:</b></label>
@ -201,13 +213,6 @@
<span class="help-inline">{{ form.speakers.errors }}</span> <span class="help-inline">{{ form.speakers.errors }}</span>
</div> </div>
</div> </div>
{# audience #}
<div class="control-group {% if form.audience.errors %}error{% endif %}">
<label class="control-label">{{ form.audience.label }}:</label>
<div class="controls">{{ form.audience }}
<span class="help-inline">{{ form.audience.errors }}</span>
</div>
</div>
</div> </div>
{# logo #} {# logo #}
<div class="control-group {% if form.logo.errors %}error{% endif %}"> <div class="control-group {% if form.logo.errors %}error{% endif %}">

@ -1,4 +1,6 @@
{% load widget_tweaks %}
{% comment %} {% comment %}
Usage: used for creating multilanguage tabs Usage: used for creating multilanguage tabs
Uses form, languages dictionary and field which will be in tabs Uses form, languages dictionary and field which will be in tabs
@ -29,11 +31,14 @@
{% ifequal f.name lang_field %} {% ifequal f.name lang_field %}
<div class="control-group {% if f.errors %}error{% endif %}" > <div class="control-group {% if f.errors %}error{% endif %}" >
<label class="control-label"> <label class="control-label">
{% if f.field.required %} <b> {% endif %} {# if field required label - bold #} {% if f.field.required %}
{{f.label}}: <b>{{ f.label }}:</b>
{% if f.field.required %} </b> {% endif %} {% else %}
{{ f.label }}:
{% endif %} {# if field required label - bold #}
</label> </label>
<div class="controls" style="border: 1px solid #ddd; padding: 10px; border-radius: 5px">{{f}}{# style for making content border #} <div class="controls" style="border: 1px solid #ddd; padding: 10px; border-radius: 5px">
{% if f.field.required %}{{ f|attr:"required" }}{% else %}{{ f }}{% endif %} {# style for making content border #}
<span class="help-inline"> {{f.errors}}</span></div> <span class="help-inline"> {{f.errors}}</span></div>
</div> </div>
{% endifequal %} {% endifequal %}

@ -53,26 +53,29 @@
</div> </div>
</div> </div>
<div class="rq-to-hide"> {% if object.get_similar %}
<div class="s-comments"> <div class="rq-to-hide">
<div class="sect-title blog_link"><span>{% trans 'Последние новости' %}</span><a class="button more" href="/news/">{% trans 'Все новости' %}</a></div> <div class="s-comments">
<div class="cat-list sc-comments"> <div class="sect-title blog_link"><span>{% trans 'Другие новости, которые могут быть вам интересны' %}</span><a class="button more" href="/news/">{% trans 'Все новости' %}</a></div>
{% for news in object.similar %} <div class="cat-list sc-comments">
<div class="cl-item"> {% for news in object.get_similar %}
<div class="acticle_list"> <div class="cl-item">
<a href="{{ news.get_permanent_url }}" title=""> <div class="acticle_list">
<span class="cli-pict"> <a href="{{ news.get_permanent_url }}" title="">
{% include 'includes/show_logo.html' with obj=news %} <span class="cli-pict">
</span> {% include 'includes/show_logo.html' with obj=news %}
</a> </span>
<h3><a href="{{ news.get_permanent_url }}" title="">{{ news.main_title }}</a></h3> </a>
<p>{{ news.preview|safe }}</p> <h3><a href="{{ news.get_permanent_url }}" title="">{{ news.main_title }}</a></h3>
<strong><span>{{ news.publish_date|date:"d E Y" }}</span>{% if news.get_event %}<a href="{{ news.get_event.get_permanent_url }}" title=""><b>{{ news.get_event.name }}</b></a><{% endif %}</strong> <p>{{ news.preview|safe }}</p>
<strong><span>{{ news.publish_date|date:"d E Y" }}</span>{% if news.get_event %}<a href="{{ news.get_event.get_permanent_url }}" title=""><b>{{ news.get_event.name }}</b></a><{% endif %}</strong>
</div>
<div class="clearfix"></div>
</div>
{% endfor %}
</div> </div>
<div class="clearfix"></div>
</div> </div>
{% endfor %}
</div> </div>
</div> {% endif %}
</div>
{% endblock %} {% endblock %}

@ -132,19 +132,24 @@
</div> </div>
<div class="conference_interested"> <div class="conference_interested">
<div class="conference_for"> {% with object.audience.all as audiences %}
<h3><i class="fa fa-user"></i> {% trans 'Кому будет интересно' %}</h3> {% if audiences %}
<ul> <div class="conference_for">
{% for audience in object.audience.all %} <h3><i class="fa fa-user"></i> {% trans 'Кому будет интересно' %}</h3>
<li>{{ audience.title }}</li> <ul>
{% endfor %} {% for audience in audiences %}
</ul> <li>{{ audience.title }}</li>
</div> {% endfor %}
<div class="confererence_price"> </ul>
<h3><i class="fa fa-tag"></i> {% trans 'Стоимость участия' %}</h3> </div>
{% endif %}
<div class="conference_price">{{ object.min_price }} - {{ object.max_price }} {{ object.get_currency_html }}</div> {% endwith %}
</div> {% if object.min_price and object.max_price %}
<div class="confererence_price">
<h3><i class="fa fa-tag"></i> {% trans 'Стоимость участия' %}</h3>
<div class="conference_price">{{ object.min_price }} - {{ object.max_price }} {{ object.get_currency_html }}</div>
</div>
{% endif %}
</div> </div>
<hr> <hr>

@ -1,16 +1,16 @@
{% extends "client/base_catalog.html" %} {% extends "client/base_catalog.html" %}
{% load i18n %} {% load i18n %}
{% block title %}{% trans "Email confirmation" %}{% endblock %} {% block title %}{% trans "Подтверждение email" %}{% endblock %}
{% block page_body %} {% block page_body %}
<h1>{% trans "Enter your email" %}</h1> <h1>{% trans "Введите ваш email" %}</h1>
<div cl> <div cl>
</div> </div>
{% if form.errors %} {% if form.errors %}
<p class="error">{% trans "Please correct the errors below:" %}</p> <p class="error">{% trans "Пожалуйста исправьте ошибки:" %}</p>
{% endif %} {% endif %}
{# {% url "social:complete" backend=backend %}#} {# {% url "social:complete" backend=backend %}#}
<form class="form-inline" action="." method="post" role="form">{% csrf_token %} <form class="form-inline" action="." method="post" role="form">{% csrf_token %}
@ -22,11 +22,12 @@
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
<button class="btn btn-default" type="submit">{% trans "Submit" %}</button> <button class="btn btn-default" type="submit">{% trans "Подтвердить" %}</button>
</form> </form>
{% endblock %} {% endblock %}
{% block content-related %} {% block content-related %}
<p>{% trans "Please enter your valid email, to activate account we will send you an email on this e-mail address" %}</p> <p>{% trans "Пожалуйста введите ваш email. Мы вышлем на него письмо чтобы активировать аккаунт." %}</p>
{#<p>{% trans "Please enter your valid email, to activate account we will send you an email on this e-mail address" %}</p>#}
{% endblock %} {% endblock %}

Loading…
Cancel
Save