almost done

remotes/origin/search
Alexander Burdeiny 10 years ago
parent 60ece0c155
commit 2ba6556e01
  1. 5
      article/admin.py
  2. 26
      article/forms.py
  3. 1
      article/models.py
  4. 8
      article/views.py
  5. 2
      templates/admin/includes/admin_nav.html
  6. 9
      templates/admin/theme/theme_add.html
  7. 2
      templates/client/article/article.html
  8. 6
      templates/client/includes/article_theme.html
  9. 94
      theme/admin.py
  10. 17
      theme/admin_urls.py
  11. 49
      theme/forms.py
  12. 14
      theme/management/commands/themeblog_to_blog.py
  13. 26
      theme/models.py

@ -171,10 +171,7 @@ class BlogView(FormView):
article = self.obj article = self.obj
data = {} data = {}
data['slug'] = article.slug data['slug'] = article.slug
if self.obj.type == Article.blog: data['theme'] = [item.id for item in article.theme.all()]
data['theme'] = [item.id for item in article.blog_theme.all()]
else:
data['theme'] = [item.id for item in article.theme.all()]
if article.exposition: if article.exposition:
data['exposition'] = article.exposition.id data['exposition'] = article.exposition.id
if article.conference: if article.conference:

@ -9,15 +9,19 @@ from functions.files import check_tmp_files
from functions.form_check import translit_with_separator from functions.form_check import translit_with_separator
from models import Article from models import Article
from accounts.models import User from accounts.models import User
from theme.models import Theme, Tag, ThemeBlog from theme.models import Theme, Tag
from exposition.models import Exposition from exposition.models import Exposition
from conference.models import Conference from conference.models import Conference
class _BlogForm(forms.Form): class _BlogForm(forms.Form):
type = Article.blog type = Article.blog
theme = forms.ModelMultipleChoiceField(label='Тематики', queryset=ThemeBlog.objects.all(), required=False, theme = forms.ModelMultipleChoiceField(
widget=forms.SelectMultiple(attrs={'style':'width: 550px'})) label='Тематики',
queryset=Theme.objects.filter(types=Theme.types.article),
required=False,
widget=forms.SelectMultiple(attrs={'style':'width: 550px'})
)
slug = forms.SlugField(label=u'URL', max_length=255, min_length=1, required=False) slug = forms.SlugField(label=u'URL', max_length=255, min_length=1, required=False)
publish_date = forms.DateField(label=u'Дата публикации', input_formats=['%Y-%m-%d', '%d.%m.%Y'], required=False) publish_date = forms.DateField(label=u'Дата публикации', input_formats=['%Y-%m-%d', '%d.%m.%Y'], required=False)
tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(), required=False) tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(), required=False)
@ -63,12 +67,8 @@ class _BlogForm(forms.Form):
# fill translated fields and save object # fill translated fields and save object
fill_with_signal(Article, article, data) fill_with_signal(Article, article, data)
# fill manytomany fields # fill manytomany fields
if self.type == Article.blog: article.theme.clear()
article.blog_theme.clear() article.theme.add(*Theme.objects.filter(id__in=data['theme']))
article.blog_theme.add(*ThemeBlog.objects.filter(id__in=data['theme']))
else:
article.theme.clear()
article.theme.add(*Theme.objects.filter(id__in=data['theme']))
article.tag.clear() article.tag.clear()
article.tag.add(*Tag.objects.filter(id__in=data['tag'])) article.tag.add(*Tag.objects.filter(id__in=data['tag']))
#for item in data['theme']: #for item in data['theme']:
@ -301,9 +301,11 @@ class BlogFilterForm(forms.Form):
create dynamical translated fields fields create dynamical translated fields fields
""" """
super(BlogFilterForm, self).__init__(*args, **kwargs) super(BlogFilterForm, self).__init__(*args, **kwargs)
ids = set([item['blog_theme'] for item in list(Article.objects.blogs().filter(blog_theme__isnull=False).values('blog_theme'))]) ids = set(Article.objects.filter(type=Article.blog, theme__isnull=False).values_list('theme', flat=True))
self.fields['theme'] = forms.MultipleChoiceField(label=_(u'Тематика:'), required=False, # ids = set([item['theme'] for item in list(Article.objects.blogs().filter(theme__isnull=False).values('theme'))])
choices=[(item.id, item.name) for item in ThemeBlog.objects.language().filter(id__in=ids)]) self.fields['theme'] = forms.MultipleChoiceField(label=_(u'Тематика:'),
required=False,
choices=[(item.id, item.name) for item in Theme.objects.language().filter(id__in=ids)])
class NewsFilterForm(forms.Form): class NewsFilterForm(forms.Form):

@ -31,7 +31,6 @@ class Article(TranslatableModel):
old_id = models.IntegerField(verbose_name=_(u'Id из старой базы'), blank=True, null=True) old_id = models.IntegerField(verbose_name=_(u'Id из старой базы'), blank=True, null=True)
logo = ImageField(verbose_name=_(u'Логотип'), upload_to='articles_preview', blank=True) logo = ImageField(verbose_name=_(u'Логотип'), upload_to='articles_preview', blank=True)
theme = models.ManyToManyField('theme.Theme', verbose_name=_(u'Тематики')) theme = models.ManyToManyField('theme.Theme', verbose_name=_(u'Тематики'))
blog_theme = models.ManyToManyField('theme.ThemeBlog', verbose_name=_(u'Тематики для блогов'), )
tag = models.ManyToManyField('theme.Tag', blank=True, null=True, verbose_name=_(u'Теги'), ) tag = models.ManyToManyField('theme.Tag', blank=True, null=True, verbose_name=_(u'Теги'), )
author = models.ForeignKey('accounts.User', verbose_name=_(u'Автор'), author = models.ForeignKey('accounts.User', verbose_name=_(u'Автор'),
on_delete=models.PROTECT, related_name='articles') on_delete=models.PROTECT, related_name='articles')

@ -7,7 +7,7 @@ from django.utils.translation import ugettext as _
from functions.custom_views import ListView from functions.custom_views import ListView
from models import Article from models import Article
from forms import BlogFilterForm, NewsFilterForm from forms import BlogFilterForm, NewsFilterForm
from theme.models import Tag, ThemeBlog from theme.models import Tag, Theme
from meta.views import MetadataMixin from meta.views import MetadataMixin
@ -80,7 +80,7 @@ class BlogList(MetadataMixin, ListView):
themes = self.request.GET.getlist('theme') themes = self.request.GET.getlist('theme')
if themes: if themes:
qs = qs.filter(blog_theme__id__in=themes) qs = qs.filter(theme__id__in=themes)
tags = self.request.GET.getlist('tag') tags = self.request.GET.getlist('tag')
if u'' in tags: if u'' in tags:
@ -192,10 +192,10 @@ class BlogsFilterCatalog(MetadataMixin, ListView):
self.filter_object = tag self.filter_object = tag
qs = Article.objects.blogs().filter(tag=tag) qs = Article.objects.blogs().filter(tag=tag)
else: else:
theme = get_object_or_404(ThemeBlog, url=slug) theme = get_object_or_404(Theme, url=slug)
self.kwargs['theme'] = theme self.kwargs['theme'] = theme
self.filter_object = theme self.filter_object = theme
qs = Article.objects.blogs().filter(blog_theme = theme) qs = Article.objects.blogs().filter(theme=theme)
year = self.kwargs.get('year') year = self.kwargs.get('year')
if year: if year:

@ -41,7 +41,7 @@
<li><a href="/admin/country/all">Страна</a></li> <li><a href="/admin/country/all">Страна</a></li>
<li><a href="/admin/city/all">Город</a></li> <li><a href="/admin/city/all">Город</a></li>
<li><a href="/admin/theme/theme/all">Тематики</a></li> <li><a href="/admin/theme/theme/all">Тематики</a></li>
<li><a href="/admin/theme/blog_theme/all">Тематики для блогов</a></li> {# <li><a href="/admin/theme/blog_theme/all">Тематики для блогов</a></li> #}
<li><a href="/admin/theme/tag/all">Теги</a></li> <li><a href="/admin/theme/tag/all">Теги</a></li>
<li><a href="/admin/service/all">Услуги</a></li> <li><a href="/admin/service/all">Услуги</a></li>
<li><a href="{% url 'linked_service_all' %}">Управление услугами</a></li> <li><a href="{% url 'linked_service_all' %}">Управление услугами</a></li>

@ -35,15 +35,6 @@
<span class="help-inline">{{ form.types.errors }}</span> <span class="help-inline">{{ form.types.errors }}</span>
</div> </div>
</div> </div>
{# blogtheme_linking #}
<div class="control-group {% if form.blogtheme_linking.errors %}error{% endif %}">
<label class="control-label">{{ form.blogtheme_linking.label }}:</label>
<div class="controls">
{{ form.blogtheme_linking }}
<span class="help-inline">{{ form.blogtheme_linking.errors }}</span>
<p class="text-primary">{{ form.blogtheme_linking.help_text }} </p>
</div>
</div>
{# main_title #} {# main_title #}
{% with field='main_title' form=form languages=languages %} {% with field='main_title' form=form languages=languages %}
{% include 'admin/forms/multilang.html' %} {% include 'admin/forms/multilang.html' %}

@ -19,7 +19,7 @@
{% include 'client/includes/article/article_logo.html' with obj=object %} {% include 'client/includes/article/article_logo.html' with obj=object %}
<h1>{{ object.main_title }}</h1> <h1>{{ object.main_title }}</h1>
<strong><span>{{ object.publish_date|date:"d E Y" }}</span>{% if object.blog_theme.all.exists %}{% include 'client/includes/article_theme.html' with obj=object %}{% endif %}</strong> <strong><span>{{ object.publish_date|date:"d E Y" }}</span>{% if object.theme.all.exists %}{% include 'client/includes/article_theme.html' with obj=object %}{% endif %}</strong>
{% if request.user.is_admin %} {% if request.user.is_admin %}
<a target="_blank" class="button green " href="/admin/article/blog/{{ object.slug }}/">{% trans 'изменить' %}</a> <a target="_blank" class="button green " href="/admin/article/blog/{{ object.slug }}/">{% trans 'изменить' %}</a>
{% endif %} {% endif %}

@ -1,6 +1,6 @@
{% with theme=obj.blog_theme.all %} {% with theme=obj.theme.all %}
{% for theme in obj.blog_theme.all %} {% for theme in obj.theme.all %}
<a href="{{ obj.get_catalog }}theme/{{ theme.url }}/" title="">{{ theme.name }}</a>{% if forloop.counter != themes|length %},{% endif %} <a href="{{ obj.get_catalog }}theme/{{ theme.url }}/" title="">{{ theme.name }}</a>{% if forloop.counter != themes|length %},{% endif %}
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}

@ -1,4 +1,4 @@
#custom views # -*- coding: utf-8 -*-
import json import json
from django.conf import settings from django.conf import settings
@ -8,16 +8,6 @@ from django.core.urlresolvers import reverse_lazy
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.views.generic import CreateView, DeleteView, UpdateView from django.views.generic import CreateView, DeleteView, UpdateView
# -*- coding: utf-8 -*-
#forms and models
from forms import (
TagDeleteForm,
TagFilterForm,
TagForm,
ThemeDeleteForm,
ThemeFilterForm,
ThemeForm
)
from functions.admin_views import AdminListView from functions.admin_views import AdminListView
from functions.custom_views import ( from functions.custom_views import (
ListView, ListView,
@ -27,8 +17,15 @@ from functions.custom_views import (
) )
from functions.views_help import get_referer from functions.views_help import get_referer
from .forms import ThemeBlogForm from .forms import (
from .models import Tag, Theme, ThemeBlog TagDeleteForm,
TagFilterForm,
TagForm,
ThemeDeleteForm,
ThemeFilterForm,
ThemeForm
)
from .models import Tag, Theme
def theme_all(request): def theme_all(request):
@ -42,15 +39,19 @@ def tag_all(request):
def theme_add(request): def theme_add(request):
return add_object(request, ThemeForm, 'theme_add.html', '/admin/theme/theme/all') return add_object(request, ThemeForm, 'theme_add.html', '/admin/theme/theme/all')
def tag_add(request): def tag_add(request):
return add_object(request, TagForm, 'tag_add.html', '/admin/theme/tag/all') return add_object(request, TagForm, 'tag_add.html', '/admin/theme/tag/all')
def theme_delete(request, theme_id): def theme_delete(request, theme_id):
return delete_object(request, Theme, ThemeDeleteForm, theme_id, '/admin/theme/theme/all') return delete_object(request, Theme, ThemeDeleteForm, theme_id, '/admin/theme/theme/all')
def tag_delete(request, tag_id): def tag_delete(request, tag_id):
return delete_object(request, Tag, TagDeleteForm, tag_id, '/admin/theme/tag/all') return delete_object(request, Tag, TagDeleteForm, tag_id, '/admin/theme/tag/all')
@login_required @login_required
def theme_copy(request, theme_id): def theme_copy(request, theme_id):
@ -71,6 +72,7 @@ def tag_copy(request, tag_id):
tag.clone() tag.clone()
return HttpResponseRedirect(get_referer(request)) return HttpResponseRedirect(get_referer(request))
@login_required @login_required
def theme_change(request, theme_id=None): def theme_change(request, theme_id=None):
try: try:
@ -86,8 +88,6 @@ def theme_change(request, theme_id=None):
data = {} data = {}
#bitfeild #bitfeild
data['types'] = [item for item, bool in theme.types if bool==True] data['types'] = [item for item, bool in theme.types if bool==True]
data['blogtheme_linking'] = theme.blogtheme_linking
#data from translated fields #data from translated fields
for code, name in settings.LANGUAGES: for code, name in settings.LANGUAGES:
@ -112,6 +112,7 @@ def theme_change(request, theme_id=None):
return render_to_response('theme_add.html', args) return render_to_response('theme_add.html', args)
@login_required @login_required
def tag_change(request, tag_id=None): def tag_change(request, tag_id=None):
try: try:
@ -185,66 +186,3 @@ class TagListView(AdminListView):
template_name = 'admin/theme/tag_list.html' template_name = 'admin/theme/tag_list.html'
form_class = TagFilterForm form_class = TagFilterForm
model = Tag model = Tag
class ThemeBlogListView(ListView):
template_name = 'admin/theme/theme_blog_list.html'
model = ThemeBlog
paginate_by = settings.ADMIN_PAGINATION
class ThemeBlogDeleteView(DeleteView):
template_name = "admin/theme/theme_blog_confirm_delete.html"
model = ThemeBlog
success_url = reverse_lazy("theme_blog_all")
pk_url_kwarg = "theme_id"
def blog_theme_add(request):
return add_object(request, ThemeBlogForm, 'theme_blog_new.html', reverse_lazy("theme_blog_all"))
@login_required
def blog_theme_change(request, theme_id=None):
try:
theme = ThemeBlog.objects.get(id=theme_id)
except:
return HttpResponseRedirect('theme_blog_all')
if request.POST:
form = ThemeBlogForm(request.POST)
if form.is_valid():
form.save(theme_id)
return HttpResponseRedirect(reverse_lazy("theme_blog_all"))
else:
data = {}
for code, name in settings.LANGUAGES:
obj = ThemeBlog._meta.translations_model.objects.get(language_code = code,master__id=theme_id) #access to translated fields
data['name_%s'%code] = obj.name
data['description_%s'%code] = obj.description
data['main_title_%s'%code] = obj.main_title
form = ThemeBlogForm(data)
args = {}
args.update(csrf(request))
args['form'] = form
args['languages'] = settings.LANGUAGES
args['theme_id'] = theme_id
return render_to_response('admin/theme/theme_blog_new.html', args)
# ======================================================
class ThemeBlogUpdateView(UpdateView):
template_name = "admin/theme/theme_blog_new.html"
model = ThemeBlog
form_class = ThemeBlogForm
success_url = reverse_lazy("theme_blog_all")
pk_url_kwarg = "theme_id"
class ThemeBlogCreateView(CreateView):
template_name = "admin/theme/theme_blog_new.html"
model = ThemeBlog
form_class = ThemeBlogForm
success_url = reverse_lazy("theme_blog_all")

@ -1,26 +1,25 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url from django.conf.urls import include, patterns, url
from admin import TagListView, ThemeListView
from .admin import ThemeBlogCreateView, ThemeBlogUpdateView, ThemeBlogDeleteView, ThemeBlogListView
from .admin import TagListView, ThemeListView
urlpatterns = patterns('theme.admin', urlpatterns = patterns('theme.admin',
# add
url(r'^theme/add.*/$', 'theme_add'), url(r'^theme/add.*/$', 'theme_add'),
url(r'^tag/add.*/$', 'tag_add'), url(r'^tag/add.*/$', 'tag_add'),
url(r'^blog_theme/add/$', 'blog_theme_add', name = 'theme_blog_new'), # delete
url(r'^theme/delete/(?P<theme_id>\d+)/$', 'theme_delete'), url(r'^theme/delete/(?P<theme_id>\d+)/$', 'theme_delete'),
url(r'^tag/delete/(?P<tag_id>\d+)/$', 'tag_delete'), url(r'^tag/delete/(?P<tag_id>\d+)/$', 'tag_delete'),
url(r'^blog_theme/delete/(?P<theme_id>\d+)/$', ThemeBlogDeleteView.as_view(), name = 'theme_blog_delete'), # change
url(r'^theme/change/(?P<theme_id>\d+).*/$', 'theme_change'), url(r'^theme/change/(?P<theme_id>\d+).*/$', 'theme_change'),
url(r'^blog_theme/change/(?P<theme_id>\d+).*/$', 'blog_theme_change', name= "theme_blog_change"),
url(r'^tag/change/(?P<tag_id>\d+).*/$', 'tag_change'), url(r'^tag/change/(?P<tag_id>\d+).*/$', 'tag_change'),
# copy
url(r'^theme/copy/(?P<theme_id>\d+).*/$', 'theme_copy'), url(r'^theme/copy/(?P<theme_id>\d+).*/$', 'theme_copy'),
url(r'^tag/copy/(?P<tag_id>\d+).*/$', 'tag_copy'), url(r'^tag/copy/(?P<tag_id>\d+).*/$', 'tag_copy'),
#url(r'^theme/all/$', 'theme_all'), # all
#url(r'^tag/all/$', 'tag_all'),
url(r'^theme/all/$', ThemeListView.as_view()), url(r'^theme/all/$', ThemeListView.as_view()),
url(r'^blog_theme/all/$', ThemeBlogListView.as_view(), name="theme_blog_all"),
url(r'^tag/all/$', TagListView.as_view()), url(r'^tag/all/$', TagListView.as_view()),
# search
url(r'^tag/search/$', 'search_tag'), url(r'^tag/search/$', 'search_tag'),
url(r'^tag/search-without-theme/$', 'search2'), url(r'^tag/search-without-theme/$', 'search2'),
) )

@ -10,15 +10,11 @@ from functions.form_check import translit_with_separator
from functions.translate import fill_with_signal from functions.translate import fill_with_signal
from hvad.forms import TranslatableModelForm from hvad.forms import TranslatableModelForm
from .models import Tag, Theme, ThemeBlog from .models import Tag, Theme
class ThemeForm(forms.Form): class ThemeForm(forms.Form):
types = forms.MultipleChoiceField(label='Тип', required=False, choices=Theme.FLAGS, widget=forms.CheckboxSelectMultiple()) 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): def __init__(self, *args, **kwargs):
super(ThemeForm, self).__init__(*args, **kwargs) super(ThemeForm, self).__init__(*args, **kwargs)
@ -60,7 +56,6 @@ class ThemeForm(forms.Form):
#generates bitfield #generates bitfield
flag = reduce(lambda x,y: x|y, (getattr(Theme.types, item) for item in data['types'])) flag = reduce(lambda x,y: x|y, (getattr(Theme.types, item) for item in data['types']))
theme.types = flag theme.types = flag
theme.blogtheme_linking = data['blogtheme_linking']
if theme.pk and theme.url: if theme.pk and theme.url:
theme.save() theme.save()
@ -148,45 +143,3 @@ class ThemeFilterForm(AdminFilterForm):
class TagFilterForm(AdminFilterForm): class TagFilterForm(AdminFilterForm):
model = Tag model = Tag
class _ThemeBlogForm(TranslatableModelForm):
class Meta:
model = ThemeBlog
fields = ['url', 'name', 'main_title', 'description', 'inflect']
widgets = {'url':forms.TextInput(attrs={'required':False})}
def save(self, commit= True):
if not 'url' in self.cleaned_data:
self.cleaned_data['url'] = translit_with_separator(self.cleaned_data['name'])
return super(_ThemeBlogForm, self).save(commit=True)
class ThemeBlogForm(forms.Form):
def __init__(self, *args, **kwargs):
super(ThemeBlogForm, self).__init__(*args, **kwargs)
# creates translated form fields, example: name_ru, name_en
# len(10) is a hack for detect if settings.LANGUAGES is not configured it return all langs
if len(settings.LANGUAGES) in range(10):
for lid, (code, name) in enumerate(settings.LANGUAGES):
# using enumerate for detect iteration number
# first iteration is a default lang so it required fields
required = True if lid == 0 else False
self.fields['name_%s' % code] = forms.CharField(label='Название', required=required)
self.fields['main_title_%s' % code] = forms.CharField(label='Заголовок', required=required)
self.fields['description_%s' % code] = forms.CharField(label='Описание', required=False, widget=CKEditorWidget)#with saving form
def save(self, id=None):
data = self.cleaned_data
if not id:
theme = ThemeBlog()
else:
theme = ThemeBlog.objects.get(id=id)
if not getattr(theme, 'url'):
theme.url = translit_with_separator(data['name_ru'].strip()).lower()
fill_with_signal(ThemeBlog, theme, data)
if not theme.url:
theme.url = translit_with_separator(theme.name)
theme.save()

@ -1,14 +0,0 @@
from django.core.management.base import BaseCommand, CommandError
from theme.models import Theme, ThemeBlog
from article.models import Article
class Command(BaseCommand):
def handle(self, *args, **options):
for article in Article.objects.filter(type=Article.blog).prefetch_related('blog_theme'):
blogthemes = article.blog_theme.all().values_list('id', flat=True)
themes = Theme.objects.filter(
types=Theme.types.article,
blogtheme_linking_id__in=blogthemes)
article.theme.clear()
article.theme.add(*themes)

@ -43,8 +43,6 @@ class Theme(TranslatableModel):
url = models.SlugField(unique=True, max_length=255) url = models.SlugField(unique=True, max_length=255)
old_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]) 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 #translated fields
translations = TranslatedFields( translations = TranslatedFields(
name = models.CharField(max_length=255), name = models.CharField(max_length=255),
@ -142,29 +140,6 @@ class Theme(TranslatableModel):
return parent return parent
class ThemeBlog(TranslatableModel):
url = models.SlugField(unique=True, max_length=255)
translations = TranslatedFields(
name=models.CharField(max_length=255),
main_title=models.CharField(max_length=255, blank=True),
description=models.TextField(blank=True)
)
inflect = models.CharField(max_length=255, blank=True)
def __unicode__(self):
return self.lazy_translation_getter('name', unicode(self.pk))
def get_all_names(self):
return [item['name'] for item in self.translations.all().values('name')]
def get_index_text(self):
translation.activate('ru')
return ' '.join(self.get_all_names())
class Tag(TranslatableModel): class Tag(TranslatableModel):
""" """
Create Tag model Create Tag model
@ -271,7 +246,6 @@ def pre_save_handler(sender, **kwargs):
pre_save.connect(pre_save_handler, sender=Tag) pre_save.connect(pre_save_handler, sender=Tag)
post_save.connect(post_save_handler, sender=Theme) post_save.connect(post_save_handler, sender=Theme)
post_save.connect(post_save_handler, sender=ThemeBlog)
post_save.connect(post_save_handler, sender=Tag) post_save.connect(post_save_handler, sender=Tag)

Loading…
Cancel
Save