diff --git a/article/managers.py b/article/managers.py index d1f77f1a..c1be6975 100644 --- a/article/managers.py +++ b/article/managers.py @@ -47,6 +47,6 @@ class ArticleManager(TranslationManager): cached_blogs = cache.get(key) return cached_blogs else: - blogs = list(self.blogs().filter(publish_date__isnull=False).order_by('-main_page', '-publish_date')[:3]) + blogs = list(self.blogs().filter(publish_date__isnull=False).order_by('-publish_date')[:3]) cache.set(key, blogs, self.cache_time) return blogs diff --git a/exposition/forms.py b/exposition/forms.py index f64f8411..687a0393 100644 --- a/exposition/forms.py +++ b/exposition/forms.py @@ -49,8 +49,9 @@ class ExpositionCreateForm(forms.Form): #company = forms.MultipleChoiceField(label=u'Компании', required=False, # choices=[(item.id, item.name) for item in Company.objects.language().all()] ) 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()]) + theme = forms.MultipleChoiceField( + label='Тематики', + choices=[(item.id, item.name) for item in Theme.objects.language().filter(types=Theme.types.exposition)]) place = forms.ChoiceField(label=u'Место проведения', required=False, choices=places) place_alt = forms.CharField(required=False, label=u'Альтернативное место') @@ -617,4 +618,4 @@ class ExpositionFilterForm(AdminFilterForm): if month: qs = qs.filter(data_begin__month=month) - return qs \ No newline at end of file + return qs diff --git a/templates/admin/theme/theme_add.html b/templates/admin/theme/theme_add.html index 6b4bbfb8..1131164b 100644 --- a/templates/admin/theme/theme_add.html +++ b/templates/admin/theme/theme_add.html @@ -35,6 +35,15 @@ {{ form.types.errors }} + {# blogtheme_linking #} +
+ +
+ {{ form.blogtheme_linking }} + {{ form.blogtheme_linking.errors }} +

{{ form.blogtheme_linking.help_text }}

+
+
{# main_title #} {% with field='main_title' form=form languages=languages %} {% include 'admin/forms/multilang.html' %} @@ -67,4 +76,4 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/theme/admin.py b/theme/admin.py index d481feed..30d7886a 100644 --- a/theme/admin.py +++ b/theme/admin.py @@ -86,7 +86,7 @@ def theme_change(request, theme_id=None): data = {} #bitfeild data['types'] = [item for item, bool in theme.types if bool==True] - + data['blogtheme_linking'] = theme.blogtheme_linking #data from translated fields diff --git a/theme/forms.py b/theme/forms.py index 7571a784..1c9e2831 100644 --- a/theme/forms.py +++ b/theme/forms.py @@ -1,22 +1,24 @@ # -*- coding: utf-8 -*- -from django import forms -from models import Tag, Theme - -from bitfield.types import BitHandler from bitfield import BitField from bitfield.forms import BitFieldCheckboxSelectMultiple, BitFormField - -from django.conf import settings +from bitfield.types import BitHandler from ckeditor.widgets import CKEditorWidget -from functions.translate import fill_with_signal +from django import forms +from django.conf import settings from functions.admin_forms import AdminFilterForm from functions.form_check import translit_with_separator +from functions.translate import fill_with_signal +from hvad.forms import TranslatableModelForm - +from .models import Tag, Theme, ThemeBlog class ThemeForm(forms.Form): types = forms.MultipleChoiceField(label='Тип', required=False, choices=Theme.FLAGS, widget=forms.CheckboxSelectMultiple()) + blogtheme_linking = forms.ModelChoiceField( + label=u'тема для блога', queryset=ThemeBlog.objects.all(), cache_choices=True, required=False, + help_text=u'''Выберите тему для блога, которая будет заменена на текущую тему.''' + u''' После миграции данных это поле будет удалено, а у всех статей у которых указана выбранная тема, будет заменена на текущую.''') def __init__(self, *args, **kwargs): super(ThemeForm, self).__init__(*args, **kwargs) @@ -58,8 +60,10 @@ class ThemeForm(forms.Form): #generates bitfield flag = reduce(lambda x,y: x|y, (getattr(Theme.types, item) for item in data['types'])) theme.types = flag + theme.blogtheme_linking = data['blogtheme_linking'] - #theme.save() + if theme.pk and theme.url: + theme.save() fill_with_signal(Theme, theme, data) if not theme.url: @@ -145,9 +149,6 @@ class ThemeFilterForm(AdminFilterForm): class TagFilterForm(AdminFilterForm): model = Tag -from hvad.forms import TranslatableModelForm -from .models import ThemeBlog - class _ThemeBlogForm(TranslatableModelForm): class Meta: diff --git a/theme/migrations/0001_initial.py b/theme/migrations/0001_initial.py new file mode 100644 index 00000000..d54170c2 --- /dev/null +++ b/theme/migrations/0001_initial.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'ThemeTranslation' + db.create_table(u'theme_theme_translation', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('main_title', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('description', self.gf('django.db.models.fields.TextField')(blank=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)), + ('descriptions', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)), + ('keywords', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)), + ('language_code', self.gf('django.db.models.fields.CharField')(max_length=15, db_index=True)), + ('master', self.gf('django.db.models.fields.related.ForeignKey')(related_name='translations', null=True, to=orm['theme.Theme'])), + )) + db.send_create_signal(u'theme', ['ThemeTranslation']) + + # Adding unique constraint on 'ThemeTranslation', fields ['language_code', 'master'] + db.create_unique(u'theme_theme_translation', ['language_code', 'master_id']) + + # Adding model 'Theme' + db.create_table(u'theme_theme', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('url', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=255)), + ('old_url', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=255)), + ('types', self.gf('django.db.models.fields.BigIntegerField')(default=None)), + ('main_page', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, db_index=True)), + ('inflect', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)), + )) + db.send_create_signal(u'theme', ['Theme']) + + # Adding model 'ThemeBlogTranslation' + db.create_table(u'theme_themeblog_translation', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('main_title', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)), + ('description', self.gf('django.db.models.fields.TextField')(blank=True)), + ('language_code', self.gf('django.db.models.fields.CharField')(max_length=15, db_index=True)), + ('master', self.gf('django.db.models.fields.related.ForeignKey')(related_name='translations', null=True, to=orm['theme.ThemeBlog'])), + )) + db.send_create_signal(u'theme', ['ThemeBlogTranslation']) + + # Adding unique constraint on 'ThemeBlogTranslation', fields ['language_code', 'master'] + db.create_unique(u'theme_themeblog_translation', ['language_code', 'master_id']) + + # Adding model 'ThemeBlog' + db.create_table(u'theme_themeblog', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('url', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=255)), + ('inflect', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)), + )) + db.send_create_signal(u'theme', ['ThemeBlog']) + + # Adding model 'TagTranslation' + db.create_table(u'theme_tag_translation', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=100)), + ('main_title', self.gf('django.db.models.fields.CharField')(max_length=100)), + ('description', self.gf('django.db.models.fields.TextField')(blank=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=250, blank=True)), + ('descriptions', self.gf('django.db.models.fields.CharField')(max_length=250, blank=True)), + ('keywords', self.gf('django.db.models.fields.CharField')(max_length=250, blank=True)), + ('language_code', self.gf('django.db.models.fields.CharField')(max_length=15, db_index=True)), + ('master', self.gf('django.db.models.fields.related.ForeignKey')(related_name='translations', null=True, to=orm['theme.Tag'])), + )) + db.send_create_signal(u'theme', ['TagTranslation']) + + # Adding unique constraint on 'TagTranslation', fields ['language_code', 'master'] + db.create_unique(u'theme_tag_translation', ['language_code', 'master_id']) + + # Adding model 'Tag' + db.create_table(u'theme_tag', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('url', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=255)), + ('old_url', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=255)), + ('theme', self.gf('django.db.models.fields.related.ForeignKey')(related_name='tags', on_delete=models.PROTECT, to=orm['theme.Theme'])), + ('inflect', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)), + )) + db.send_create_signal(u'theme', ['Tag']) + + + def backwards(self, orm): + # Removing unique constraint on 'TagTranslation', fields ['language_code', 'master'] + db.delete_unique(u'theme_tag_translation', ['language_code', 'master_id']) + + # Removing unique constraint on 'ThemeBlogTranslation', fields ['language_code', 'master'] + db.delete_unique(u'theme_themeblog_translation', ['language_code', 'master_id']) + + # Removing unique constraint on 'ThemeTranslation', fields ['language_code', 'master'] + db.delete_unique(u'theme_theme_translation', ['language_code', 'master_id']) + + # Deleting model 'ThemeTranslation' + db.delete_table(u'theme_theme_translation') + + # Deleting model 'Theme' + db.delete_table(u'theme_theme') + + # Deleting model 'ThemeBlogTranslation' + db.delete_table(u'theme_themeblog_translation') + + # Deleting model 'ThemeBlog' + db.delete_table(u'theme_themeblog') + + # Deleting model 'TagTranslation' + db.delete_table(u'theme_tag_translation') + + # Deleting model 'Tag' + db.delete_table(u'theme_tag') + + + models = { + u'theme.tag': { + 'Meta': {'unique_together': '()', 'object_name': 'Tag', 'index_together': '()'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inflect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'old_url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}), + 'theme': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tags'", 'on_delete': 'models.PROTECT', 'to': u"orm['theme.Theme']"}), + 'url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'theme.tagtranslation': { + 'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'TagTranslation', 'db_table': "u'theme_tag_translation'", 'index_together': '()'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'descriptions': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'main_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['theme.Tag']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}) + }, + u'theme.theme': { + 'Meta': {'unique_together': '()', 'object_name': 'Theme', 'index_together': '()'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inflect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'main_page': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'db_index': 'True'}), + 'old_url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}), + 'types': ('django.db.models.fields.BigIntegerField', [], {'default': 'None'}), + 'url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'theme.themeblog': { + 'Meta': {'unique_together': '()', 'object_name': 'ThemeBlog', 'index_together': '()'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inflect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'theme.themeblogtranslation': { + 'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'ThemeBlogTranslation', 'db_table': "u'theme_themeblog_translation'", 'index_together': '()'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'main_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['theme.ThemeBlog']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + u'theme.themetranslation': { + 'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'ThemeTranslation', 'db_table': "u'theme_theme_translation'", 'index_together': '()'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'descriptions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'main_title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['theme.Theme']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + } + } + + complete_apps = ['theme'] \ No newline at end of file diff --git a/theme/migrations/0002_auto__add_field_theme_blogtheme_linking.py b/theme/migrations/0002_auto__add_field_theme_blogtheme_linking.py new file mode 100644 index 00000000..c754bc55 --- /dev/null +++ b/theme/migrations/0002_auto__add_field_theme_blogtheme_linking.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Theme.blogtheme_linking' + db.add_column(u'theme_theme', 'blogtheme_linking', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['theme.ThemeBlog'], null=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Theme.blogtheme_linking' + db.delete_column(u'theme_theme', 'blogtheme_linking_id') + + + models = { + u'theme.tag': { + 'Meta': {'unique_together': '()', 'object_name': 'Tag', 'index_together': '()'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inflect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'old_url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}), + 'theme': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tags'", 'on_delete': 'models.PROTECT', 'to': u"orm['theme.Theme']"}), + 'url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'theme.tagtranslation': { + 'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'TagTranslation', 'db_table': "u'theme_tag_translation'", 'index_together': '()'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'descriptions': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'main_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['theme.Tag']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}) + }, + u'theme.theme': { + 'Meta': {'unique_together': '()', 'object_name': 'Theme', 'index_together': '()'}, + 'blogtheme_linking': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['theme.ThemeBlog']", 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inflect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'main_page': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'db_index': 'True'}), + 'old_url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}), + 'types': ('django.db.models.fields.BigIntegerField', [], {'default': 'None'}), + 'url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'theme.themeblog': { + 'Meta': {'unique_together': '()', 'object_name': 'ThemeBlog', 'index_together': '()'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inflect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'url': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'theme.themeblogtranslation': { + 'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'ThemeBlogTranslation', 'db_table': "u'theme_themeblog_translation'", 'index_together': '()'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'main_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['theme.ThemeBlog']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + u'theme.themetranslation': { + 'Meta': {'unique_together': "[('language_code', 'master')]", 'object_name': 'ThemeTranslation', 'db_table': "u'theme_theme_translation'", 'index_together': '()'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'descriptions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), + 'main_title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['theme.Theme']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + } + } + + complete_apps = ['theme'] \ No newline at end of file diff --git a/theme/migrations/__init__.py b/theme/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/theme/models.py b/theme/models.py index 7a8e85c1..04e1a986 100644 --- a/theme/models.py +++ b/theme/models.py @@ -1,17 +1,23 @@ # -*- coding: utf-8 -*- -import datetime import copy -from django.db import models +import datetime +import random +import string + +from bitfield import BitField +from conference.models import Conference +from django.db import IntegrityError, models +from django.db.models.signals import post_save, pre_save from django.utils import translation from django.utils.translation import ugettext as _ -from hvad.models import TranslatableModel, TranslatedFields, TranslationManager -from bitfield import BitField from exposition.models import Exposition -from conference.models import Conference -from seminar.models import Seminar -from webinar.models import Webinar +from functions.form_check import translit_with_separator from functions.models_methods import ExpoManager +from functions.signal_handlers import post_save_handler +from hvad.models import TranslatableModel, TranslatedFields, TranslationManager from manager import TagActiveManager, ThemeActiveManager +from seminar.models import Seminar +from webinar.models import Webinar class Theme(TranslatableModel): @@ -32,10 +38,13 @@ class Theme(TranslatableModel): ('conference', 'Конференция'), ('seminar', 'Семинар'), ('webinar', 'Вебинар'), + ('article', 'Статья'), ) url = models.SlugField(unique=True, max_length=255) old_url = models.SlugField(unique=True, max_length=255) types = BitField([k for k, v in FLAGS]) + blogtheme_linking = models.ForeignKey('ThemeBlog', verbose_name=u'тема для блога', null=True, default=None, + help_text=u'Выберите тему для блога, которая будет заменена на текущую тему') #translated fields translations = TranslatedFields( name = models.CharField(max_length=255), @@ -156,7 +165,6 @@ class ThemeBlog(TranslatableModel): return ' '.join(self.get_all_names()) -from django.db import IntegrityError class Tag(TranslatableModel): """ Create Tag model @@ -243,15 +251,6 @@ class Tag(TranslatableModel): return parent - - - -from django.db.models.signals import post_save, pre_save -from functions.signal_handlers import post_save_handler -from functions.form_check import translit_with_separator -import random, string - - def pre_save_handler(sender, **kwargs): obj = kwargs['instance'] @@ -277,5 +276,3 @@ post_save.connect(post_save_handler, sender=Tag) #----------------------- - -