From 9fe7370f267dbc6dc1e6484fc0546553fb25cd41 Mon Sep 17 00:00:00 2001 From: Ivan Kovalkovskyi Date: Wed, 9 Sep 2015 19:02:02 +0300 Subject: [PATCH] added specialist catalog models and form. view only form specialist model, --- exposition/models.py | 13 --- proj/admin_urls.py | 1 + proj/settings.py | 3 +- specialist_catalog/__init__.py | 0 specialist_catalog/admin_urls.py | 11 +++ specialist_catalog/forms.py | 86 ++++++++++++++++++ specialist_catalog/models.py | 89 +++++++++++++++++++ specialist_catalog/tests.py | 16 ++++ specialist_catalog/urls.py | 6 ++ specialist_catalog/views.py | 30 +++++++ .../admin/specialist/specialist_all.html | 54 +++++++++++ .../specialist/specialist_confirm_delete.html | 11 +++ .../admin/specialist/specialist_new.html | 79 ++++++++++++++++ 13 files changed, 385 insertions(+), 14 deletions(-) create mode 100644 specialist_catalog/__init__.py create mode 100644 specialist_catalog/admin_urls.py create mode 100644 specialist_catalog/forms.py create mode 100644 specialist_catalog/models.py create mode 100644 specialist_catalog/tests.py create mode 100644 specialist_catalog/urls.py create mode 100644 specialist_catalog/views.py create mode 100644 templates/admin/specialist/specialist_all.html create mode 100644 templates/admin/specialist/specialist_confirm_delete.html create mode 100644 templates/admin/specialist/specialist_new.html diff --git a/exposition/models.py b/exposition/models.py index 36326f02..81474a3a 100644 --- a/exposition/models.py +++ b/exposition/models.py @@ -160,7 +160,6 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin): paid_new = models.ForeignKey('expobanner.Paid', blank=True, null=True, on_delete=models.SET_NULL) top = models.ForeignKey('expobanner.Top', blank=True, null=True, on_delete=models.SET_NULL) - main = models.ForeignKey('expobanner.MainPage', blank=True, null=True, on_delete=models.SET_NULL) #set manager of this model(fisrt manager is default) objects = ExpoManager() enable = ClientManager() @@ -309,18 +308,6 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin): def theme_ids(self): return [item['id'] for item in self.theme.all().values('id')] - def get_main_link(self): - if self.main: - return self.main.link.get_click_link() - else: - return self.get_permanent_url() - - def get_top_link(self): - if self.top: - return self.top.link.get_click_link() - else: - return self.get_permanent_url() - class Statistic(TranslatableModel): exposition = models.ForeignKey(Exposition, related_name='statistic') diff --git a/proj/admin_urls.py b/proj/admin_urls.py index 47bbfeaf..c66d75f1 100644 --- a/proj/admin_urls.py +++ b/proj/admin_urls.py @@ -34,6 +34,7 @@ urlpatterns = required( url(r'^settings/', include('settings.admin_urls')), url(r'^meta/', include('meta.admin_urls')), url(r'^import_xls/', include('import_xls.admin_urls')), + url(r'^specialist_catalog/', include('specialist_catalog.admin_urls')), url(r'^language/add/', 'directories.admin.language_add'), url(r'^currency/add/', 'directories.admin.currency_add'), diff --git a/proj/settings.py b/proj/settings.py index 0a679246..863a6fa8 100644 --- a/proj/settings.py +++ b/proj/settings.py @@ -353,7 +353,8 @@ INSTALLED_APPS = ( 'password_reset', # reset password 'social.apps.django_app.default', # social auth 'core', - 'wizard' + 'wizard', + 'specialist_catalog', ) diff --git a/specialist_catalog/__init__.py b/specialist_catalog/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/specialist_catalog/admin_urls.py b/specialist_catalog/admin_urls.py new file mode 100644 index 00000000..9e3c71d8 --- /dev/null +++ b/specialist_catalog/admin_urls.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +from django.conf.urls import url, patterns +from .views import * + +urlpaterns = patterns('', + url(r'^specialist/new/$', SpecialistCreateView.as_view(), name='specialist_new'), + url(r'^specialist/all/$', SpecialistListView.as_view(), name='specialist_all'), + url(r'^specialist/edit/(?P\d{1,4})/$', SpecialistUpdateView.as_view(), name='specialist_edit'), + url(r'^specialist/delete/(?P\d{1,4})/$', SpecialistDeleteView.as_view(), name='specialist_delete'), + +) \ No newline at end of file diff --git a/specialist_catalog/forms.py b/specialist_catalog/forms.py new file mode 100644 index 00000000..27a469e5 --- /dev/null +++ b/specialist_catalog/forms.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +from django import forms +from hvad.forms import TranslatableModelForm +from .models import Specialist, SpecialistCatalog, Feedback, City, Country +from ckeditor.widgets import CKEditorWidget +from django.utils.translation import get_language + +country_choices = [(c.id, c.name) for c in Country.objects.all()] +lang_code = get_language()[:2] + +default_text = u"Планируете посетить выставку в %s?" \ + u" Мы предлагаем Вам подобрать переводчика именно под Ваши цели и потребности. " \ + u"Специализируясь уже более 7 лет на предоставлении переводчиков на выставки и конференции " \ + u"%s, мы можем предоставить профессионалов со знанием разных " \ + u"языков на гибких для Вас условиях. Каждый заказ индивидуален для нас, " \ + u"и итоговая цена зависит от вида перевода, тематики, срочности подбора " \ + u"специалиста, города и объема работы." +default_title = u"Переводчики в %s" + + +class SpecialistCatalogForm(TranslatableModelForm): + + class Meta: + model = SpecialistCatalog + fields = '__all__' + widgets = { + 'type': forms.Select(choices=(('1', 'Country'), ('2', 'City'))), + 'city': forms.HiddenInput(attrs={'id': 'id_city'}), + 'country': forms.Select(choices=country_choices, attrs={'id': 'id_country'}), + 'main_descr': CKEditorWidget, + 'benefits': CKEditorWidget, + } + + def clean_city(self): + data = self.cleaned_data + if data.get('city'): + data['city'] = City.objects.language(lang_code).get(id=data['city']) + return data + + def clean_country(self): + data = self.cleaned_data + if data.get('country'): + data['country'] = Country.objects.language(lang_code).get(id=data['country']) + return data + + def save(self, commit=True): + place = self.cleaned_data.get('city') or self.cleaned_data.get('country') + place_inflect = place.inflect or place.name + if not self.cleaned_data['title']: + self.cleaned_data['title'] = default_title % place_inflect + if not self.cleaned_data['main_descr']: + self.cleaned_data['main_descr'] = default_text % (place_inflect, place_inflect) + return super(SpecialistCatalogForm, self).save(commit=True) + + +class SpecialistForm(forms.ModelForm): + + class Meta: + model = Specialist + fields = '__all__' + widgets = { + 'city': forms.HiddenInput(attrs={'id': 'id_city'}), + 'country': forms.Select(choices=country_choices, attrs={'id': 'id_country'}) + } + + def clean_city(self): + data = self.cleaned_data + if data.get('city'): + data['city'] = City.objects.language(lang_code).get(id=data['city']) + return data + + def clean_country(self): + data = self.cleaned_data + if data.get('country'): + data['country'] = Country.objects.language(lang_code).get(id=data['country']) + return data + + +class FeedbackForm(forms.ModelForm): + + class Meta: + model = Feedback + fields = '__all__' + widgets = { + 'text':CKEditorWidget + } \ No newline at end of file diff --git a/specialist_catalog/models.py b/specialist_catalog/models.py new file mode 100644 index 00000000..904ef1c5 --- /dev/null +++ b/specialist_catalog/models.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +from django.db import models +from django.conf import settings +from hvad.models import TranslatableModel, TranslatedFields, TranslationManager +from functions.form_check import translit_with_separator as tws +from city.models import City +from country.models import Country +from django.core.urlresolvers import reverse_lazy +import copy + + +# types of catalog +_country = 1 +_city = 2 + + +class Specialist(models.Model): + name = models.CharField(max_length=255, verbose_name=u"Полное имя") + languages = models.CharField(max_length=255, verbose_name=u"Языки") + city = models.ForeignKey(City, on_delete=models.PROTECT, verbose_name=u"Город") + country = models.ForeignKey(Country, on_delete=models.PROTECT, verbose_name=u"Страна") + photo = models.ImageField(verbose_name=u"Фото", upload_to="specialist_catalog/specialist_photo/", blank=True) + + +class SpecialistCatalog(TranslatableModel): + price = models.IntegerField(verbose_name=u"Цена", default=200) + currency = models.CharField(max_length=255, verbose_name=u"Валюта", default=u"EUR") + logo_preview = models.ImageField(verbose_name=u"Логотип", blank=True, upload_to='/specialist_catalog/logo_preview/') + place_photo = models.ImageField(verbose_name=u"Фото для города", blank=True, upload_to='/specialist_catalog/place_photo/') + specialists = models.ManyToManyField(Specialist, verbose_name=u"Специалисты", blank=True) + city = models.ForeignKey(City, on_delete=models.PROTECT, verbose_name=u"Город") + country = models.ForeignKey(Country, on_delete=models.PROTECT, verbose_name=u"Страна") + type = models.PositiveSmallIntegerField(verbose_name=u"Тип(Страна/Город)", default=2) + + translations = TranslatedFields( + title=models.CharField(max_length=255, verbose_name=u"Заголовок"), + main_descr=models.CharField(max_length=1000, verbose_name=u"Краткое описание"), + benefits=models.CharField(max_length=2000, verbose_name=u"Преимущества") + ) + + def __init__(self, *args, **kwargs): + super(SpecialistCatalog, self).__init__(*args, **kwargs) + self.cache_fields = ['title', 'main_descr', 'benefits'] + self.is_new = True + + def get_absolute_url(self): + global _country, _city + if self.type == _country: + return reverse_lazy('spec_catalog_country', tws(self.country.name)) + else: + return reverse_lazy('spec_catalog_city', tws(self.city.name)) + + def save(self, *args, **kwargs): + super(SpecialistCatalog, 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) + 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(tr, 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 + + +class Feedback(models.Model): + company = models.CharField(max_length=255, verbose_name=u"Название компании") + name = models.CharField(max_length=100, verbose_name=u"Имя") + text = models.CharField(max_length=5000, verbose_name=u"Текст отзыва") + logo = models.ImageField(verbose_name=u"Логотип компании", upload_to='/specialist_catalog/feedback_logo/', blank=True) + catalog = models.ForeignKey(SpecialistCatalog, verbose_name=u"Страница") + + diff --git a/specialist_catalog/tests.py b/specialist_catalog/tests.py new file mode 100644 index 00000000..501deb77 --- /dev/null +++ b/specialist_catalog/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/specialist_catalog/urls.py b/specialist_catalog/urls.py new file mode 100644 index 00000000..e4fb7c7b --- /dev/null +++ b/specialist_catalog/urls.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from django.conf.urls import url, patterns +from .views import * + +urlpaterns = patterns('', +) \ No newline at end of file diff --git a/specialist_catalog/views.py b/specialist_catalog/views.py new file mode 100644 index 00000000..68c87f24 --- /dev/null +++ b/specialist_catalog/views.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from django.views.generic import CreateView, UpdateView, DeleteView, ListView, DetailView +from .forms import * +from django.core.urlresolvers import reverse + + +class SpecialistCreateView(CreateView): + form_class = SpecialistForm + model = Specialist + template_name = 'admin/specialist/specialist_new.html' + success_url = reverse("specialist_all") + + +class SpecialistListView(ListView): + model = Specialist + template_name = 'admin/specialist/specialist_all.html' + + +class SpecialistUpdateView(UpdateView): + form_class = SpecialistForm + model = Specialist + template_name = 'admin/specialist/specialist_new.html' + success_url = reverse("specialist_all") + + +class SpecialistDeleteView(DeleteView): + model = Specialist + template_name = 'admin/specialist/specialist_confirm_delete.html' + success_url = reverse("specialist_all") + diff --git a/templates/admin/specialist/specialist_all.html b/templates/admin/specialist/specialist_all.html new file mode 100644 index 00000000..b4c33f27 --- /dev/null +++ b/templates/admin/specialist/specialist_all.html @@ -0,0 +1,54 @@ +{% extends 'base.html' %} +{% block body %} +
+
+

Список специалистов(переводчиков)

+
+
+ + + + + + + + + + + {% for item in object_list %} + + + + + + + + + {% endfor %} + +
ИмяЗаголовок 
{{ item.url }}{{ item.title }} + + Изменить + + + + Удалить + +
+ + Добавить seo-текст +
+ + +
+{% endblock %} \ No newline at end of file diff --git a/templates/admin/specialist/specialist_confirm_delete.html b/templates/admin/specialist/specialist_confirm_delete.html new file mode 100644 index 00000000..90cc492c --- /dev/null +++ b/templates/admin/specialist/specialist_confirm_delete.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% block sidebar %}{% endblock %} +{% block body %} +
{% csrf_token %} +
+

Вы точно хотите удалить seo-текст "{{ object.title }}" для страницы ?

+ + Нет +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/admin/specialist/specialist_new.html b/templates/admin/specialist/specialist_new.html new file mode 100644 index 00000000..04182684 --- /dev/null +++ b/templates/admin/specialist/specialist_new.html @@ -0,0 +1,79 @@ +{% extends 'base.html' %} +{% load static %} +{# Displays article form #} + + {% block scripts %} + + + {# selects #} + + + + {# ajax #} + + + + {% endblock %} + +{% block body %} + {{ request.LANGUAGE_CODE }} +
{% csrf_token %} +
+
+
+

Основная информация

+
+
+ {# url/slug #} +
+ +
+ {{ form.langs }} + {{ form.url }} + {{ form.url.errors }} +
+
+ {# title #} +
+ +
+ {{ form.title }} + {{ form.title.errors }} +
+
+ {# page title #} +
+ +
+ {{ form.page_title }} + {{ form.page_title.errors }} +
+
+ {# description #} +
+ +
+ {{ form.description }} + {{ form.description.errors }} +
+
+ {# body #} +
+ +
+ {{ form.body }} + {{ form.body.errors }} +
+
+
+
+ +
+ + + +
+
+
+ +{% endblock %}