From 5961d6b80ffcd85e791f7f7c073ae820a1ef985e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 5 Dec 2021 14:34:46 +0000 Subject: [PATCH] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- LICENSE.txt | 1 - categories/__init__.py | 24 ++- categories/admin.py | 74 ++++---- categories/apps.py | 15 +- categories/base.py | 96 +++++----- categories/editor/settings.py | 10 +- .../editor/static/editor/jquery.treeTable.css | 2 +- .../editor/static/editor/jquery.treeTable.js | 2 +- .../editor/grappelli_tree_list_results.html | 2 +- .../templates/admin/editor/tree_editor.html | 2 +- .../templatetags/admin_tree_list_tags.py | 70 ++++---- categories/editor/tree_editor.py | 170 ++++++++++-------- categories/fields.py | 11 +- categories/fixtures/musicgenres.json | 2 +- categories/fixtures/test_category_spaces.txt | 2 +- categories/fixtures/test_category_tabs.txt | 2 +- categories/genericcollection.py | 13 +- categories/locale/it/LC_MESSAGES/django.po | 1 - .../commands/add_category_fields.py | 8 +- .../commands/drop_category_field.py | 15 +- .../management/commands/import_categories.py | 27 +-- categories/migration.py | 12 +- categories/migrations/0001_initial.py | 132 ++++++++++---- .../migrations/0002_auto_20170217_1111.py | 21 ++- .../migrations/0003_auto_20200306_1050.py | 33 ++-- .../migrations/0004_auto_20200517_1832.py | 14 +- categories/models.py | 88 +++++---- categories/registration.py | 70 ++++---- categories/settings.py | 44 ++--- categories/static/js/genericcollections.js | 2 +- .../templates/categories/ancestors_ul.html | 2 +- categories/templates/categories/base.html | 2 +- .../templates/categories/breadcrumbs.html | 2 +- .../templates/categories/category_detail.html | 2 +- .../templates/categories/category_list.html | 2 +- categories/templates/categories/ul_tree.html | 2 +- categories/templatetags/category_tags.py | 102 ++++++----- categories/tests/test_admin.py | 66 +++---- categories/tests/test_category_import.py | 35 ++-- categories/tests/test_manager.py | 5 +- categories/tests/test_mgmt_commands.py | 10 +- categories/tests/test_models.py | 11 +- categories/tests/test_registration.py | 36 ++-- categories/tests/test_templatetags.py | 49 ++--- categories/tests/test_views.py | 64 +++---- categories/urls.py | 18 +- categories/views.py | 101 +++++------ doc_src/_static/default.css | 2 +- doc_src/_static/toc.js | 2 +- doc_src/adding_the_fields.rst | 2 +- doc_src/code_examples/custom_categories1.py | 2 +- doc_src/code_examples/custom_categories3.py | 28 ++- doc_src/code_examples/custom_categories4.py | 3 +- doc_src/code_examples/custom_categories5.py | 4 +- doc_src/code_examples/custom_categories6.py | 6 +- doc_src/code_examples/custom_categories7.py | 29 +-- doc_src/conf.py | 25 ++- doc_src/index.rst | 1 - doc_src/reference/management_commands.rst | 2 +- doc_src/reference/settings.rst | 2 +- doc_src/usage.rst | 1 - doc_src/usage_example_template.html | 2 +- example/settings-testing.py | 127 +++++++------ example/settings.py | 130 +++++++------- example/simpletext/admin.py | 17 +- example/simpletext/migrations/0001_initial.py | 53 +++--- .../migrations/0002_auto_20171204_0721.py | 37 ++-- .../migrations/0003_auto_20200306_0928.py | 14 +- example/simpletext/models.py | 15 +- example/simpletext/tests.py | 6 +- example/static/editor/jquery.treeTable.css | 2 +- example/static/editor/jquery.treeTable.js | 2 +- example/static/js/genericcollections.js | 2 +- example/urls.py | 15 +- 74 files changed, 1079 insertions(+), 926 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 57bc88a..261eeb9 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -199,4 +199,3 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - diff --git a/categories/__init__.py b/categories/__init__.py index 7808fc0..0dad974 100644 --- a/categories/__init__.py +++ b/categories/__init__.py @@ -1,23 +1,19 @@ -__version_info__ = { - 'major': 1, - 'minor': 8, - 'micro': 0, - 'releaselevel': 'final', - 'serial': 1 -} +__version_info__ = {"major": 1, "minor": 8, "micro": 0, "releaselevel": "final", "serial": 1} def get_version(short=False): - assert __version_info__['releaselevel'] in ('alpha', 'beta', 'final') - vers = ["%(major)i.%(minor)i" % __version_info__, ] - if __version_info__['micro'] and not short: + assert __version_info__["releaselevel"] in ("alpha", "beta", "final") + vers = [ + "%(major)i.%(minor)i" % __version_info__, + ] + if __version_info__["micro"] and not short: vers.append(".%(micro)i" % __version_info__) - if __version_info__['releaselevel'] != 'final' and not short: - vers.append('%s%i' % (__version_info__['releaselevel'][0], __version_info__['serial'])) - return ''.join(vers) + if __version_info__["releaselevel"] != "final" and not short: + vers.append("%s%i" % (__version_info__["releaselevel"][0], __version_info__["serial"])) + return "".join(vers) __version__ = get_version() -default_app_config = 'categories.apps.CategoriesConfig' +default_app_config = "categories.apps.CategoriesConfig" diff --git a/categories/admin.py b/categories/admin.py index 5c0eaba..5c11755 100644 --- a/categories/admin.py +++ b/categories/admin.py @@ -1,17 +1,17 @@ -from django.contrib import admin from django import forms +from django.contrib import admin from django.utils.translation import ugettext_lazy as _ +from .base import CategoryBaseAdmin, CategoryBaseAdminForm from .genericcollection import GenericCollectionTabularInline -from .settings import RELATION_MODELS, JAVASCRIPT_URL, REGISTER_ADMIN from .models import Category -from .base import CategoryBaseAdminForm, CategoryBaseAdmin -from .settings import MODEL_REGISTRY +from .settings import JAVASCRIPT_URL, MODEL_REGISTRY, REGISTER_ADMIN, RELATION_MODELS class NullTreeNodeChoiceField(forms.ModelChoiceField): """A ModelChoiceField for tree nodes.""" - def __init__(self, level_indicator='---', *args, **kwargs): + + def __init__(self, level_indicator="---", *args, **kwargs): self.level_indicator = level_indicator super(NullTreeNodeChoiceField, self).__init__(*args, **kwargs) @@ -20,7 +20,7 @@ class NullTreeNodeChoiceField(forms.ModelChoiceField): Creates labels which represent the tree level of each node when generating option labels. """ - return '%s %s' % (self.level_indicator * getattr(obj, obj._mptt_meta.level_attr), obj) + return "%s %s" % (self.level_indicator * getattr(obj, obj._mptt_meta.level_attr), obj) if RELATION_MODELS: @@ -33,38 +33,43 @@ if RELATION_MODELS: class CategoryAdminForm(CategoryBaseAdminForm): class Meta: model = Category - fields = '__all__' + fields = "__all__" def clean_alternate_title(self): - if self.instance is None or not self.cleaned_data['alternate_title']: - return self.cleaned_data['name'] + if self.instance is None or not self.cleaned_data["alternate_title"]: + return self.cleaned_data["name"] else: - return self.cleaned_data['alternate_title'] + return self.cleaned_data["alternate_title"] class CategoryAdmin(CategoryBaseAdmin): form = CategoryAdminForm - list_display = ('name', 'alternate_title', 'active') + list_display = ("name", "alternate_title", "active") fieldsets = ( - (None, { - 'fields': ('parent', 'name', 'thumbnail', 'active') - }), - (_('Meta Data'), { - 'fields': ('alternate_title', 'alternate_url', 'description', - 'meta_keywords', 'meta_extra'), - 'classes': ('collapse',), - }), - (_('Advanced'), { - 'fields': ('order', 'slug'), - 'classes': ('collapse',), - }), + (None, {"fields": ("parent", "name", "thumbnail", "active")}), + ( + _("Meta Data"), + { + "fields": ("alternate_title", "alternate_url", "description", "meta_keywords", "meta_extra"), + "classes": ("collapse",), + }, + ), + ( + _("Advanced"), + { + "fields": ("order", "slug"), + "classes": ("collapse",), + }, + ), ) if RELATION_MODELS: - inlines = [InlineCategoryRelation, ] + inlines = [ + InlineCategoryRelation, + ] class Media: - js = (JAVASCRIPT_URL + 'genericcollections.js',) + js = (JAVASCRIPT_URL + "genericcollections.js",) if REGISTER_ADMIN: @@ -72,18 +77,21 @@ if REGISTER_ADMIN: for model, modeladmin in list(admin.site._registry.items()): if model in list(MODEL_REGISTRY.values()) and modeladmin.fieldsets: - fieldsets = getattr(modeladmin, 'fieldsets', ()) - fields = [cat.split('.')[2] for cat in MODEL_REGISTRY if MODEL_REGISTRY[cat] == model] + fieldsets = getattr(modeladmin, "fieldsets", ()) + fields = [cat.split(".")[2] for cat in MODEL_REGISTRY if MODEL_REGISTRY[cat] == model] # check each field to see if already defined for cat in fields: for k, v in fieldsets: - if cat in v['fields']: + if cat in v["fields"]: fields.remove(cat) # if there are any fields left, add them under the categories fieldset if len(fields) > 0: admin.site.unregister(model) - admin.site.register(model, type('newadmin', (modeladmin.__class__,), { - 'fieldsets': fieldsets + (('Categories', { - 'fields': fields - }),) - })) + admin.site.register( + model, + type( + "newadmin", + (modeladmin.__class__,), + {"fieldsets": fieldsets + (("Categories", {"fields": fields}),)}, + ), + ) diff --git a/categories/apps.py b/categories/apps.py index 02e70e0..1bc058e 100644 --- a/categories/apps.py +++ b/categories/apps.py @@ -2,16 +2,18 @@ from django.apps import AppConfig class CategoriesConfig(AppConfig): - name = 'categories' + name = "categories" verbose_name = "Categories" def __init__(self, *args, **kwargs): super(CategoriesConfig, self).__init__(*args, **kwargs) from django.db.models.signals import class_prepared + class_prepared.connect(handle_class_prepared) def ready(self): from django.db.models.signals import post_migrate + from .migration import migrate_app post_migrate.connect(migrate_app) @@ -21,17 +23,18 @@ def handle_class_prepared(sender, **kwargs): """ See if this class needs registering of fields """ - from .settings import M2M_REGISTRY, FK_REGISTRY from .registration import registry + from .settings import FK_REGISTRY, M2M_REGISTRY + sender_app = sender._meta.app_label sender_name = sender._meta.model_name for key, val in list(FK_REGISTRY.items()): - app_name, model_name = key.split('.') + app_name, model_name = key.split(".") if app_name == sender_app and sender_name == model_name: - registry.register_model(app_name, sender, 'ForeignKey', val) + registry.register_model(app_name, sender, "ForeignKey", val) for key, val in list(M2M_REGISTRY.items()): - app_name, model_name = key.split('.') + app_name, model_name = key.split(".") if app_name == sender_app and sender_name == model_name: - registry.register_model(app_name, sender, 'ManyToManyField', val) + registry.register_model(app_name, sender, "ManyToManyField", val) diff --git a/categories/base.py b/categories/base.py index 29319f4..9517565 100644 --- a/categories/base.py +++ b/categories/base.py @@ -4,25 +4,23 @@ with customizable metadata and its own name space. """ import sys +from django import forms from django.contrib import admin from django.db import models -from django import forms from django.utils.encoding import force_text - -from mptt.models import MPTTModel +from django.utils.translation import ugettext_lazy as _ from mptt.fields import TreeForeignKey from mptt.managers import TreeManager +from mptt.models import MPTTModel from slugify import slugify from .editor.tree_editor import TreeEditor from .settings import ALLOW_SLUG_CHANGE, SLUG_TRANSLITERATOR -from django.utils.translation import ugettext_lazy as _ - - if sys.version_info[0] < 3: # Remove this after dropping support of Python 2 from django.utils.encoding import python_2_unicode_compatible else: + def python_2_unicode_compatible(x): return x @@ -31,6 +29,7 @@ class CategoryManager(models.Manager): """ A manager that adds an "active()" method for all active categories """ + def active(self): """ Only categories that are active @@ -44,17 +43,18 @@ class CategoryBase(MPTTModel): This base model includes the absolute bare bones fields and methods. One could simply subclass this model and do nothing else and it should work. """ + parent = TreeForeignKey( - 'self', + "self", on_delete=models.CASCADE, blank=True, null=True, - related_name='children', - verbose_name=_('parent'), + related_name="children", + verbose_name=_("parent"), ) - name = models.CharField(max_length=100, verbose_name=_('name')) - slug = models.SlugField(verbose_name=_('slug')) - active = models.BooleanField(default=True, verbose_name=_('active')) + name = models.CharField(max_length=100, verbose_name=_("name")) + slug = models.SlugField(verbose_name=_("slug")) + active = models.BooleanField(default=True, verbose_name=_("active")) objects = CategoryManager() tree = TreeManager() @@ -78,23 +78,28 @@ class CategoryBase(MPTTModel): def __str__(self): ancestors = self.get_ancestors() - return ' > '.join([force_text(i.name) for i in ancestors] + [self.name, ]) + return " > ".join( + [force_text(i.name) for i in ancestors] + + [ + self.name, + ] + ) class Meta: abstract = True - unique_together = ('parent', 'name') - ordering = ('tree_id', 'lft') + unique_together = ("parent", "name") + ordering = ("tree_id", "lft") class MPTTMeta: - order_insertion_by = 'name' + order_insertion_by = "name" class CategoryBaseAdminForm(forms.ModelForm): def clean_slug(self): - if not self.cleaned_data.get('slug', None): + if not self.cleaned_data.get("slug", None): if self.instance is None or not ALLOW_SLUG_CHANGE: - self.cleaned_data['slug'] = slugify(SLUG_TRANSLITERATOR(self.cleaned_data['name'])) - return self.cleaned_data['slug'][:50] + self.cleaned_data["slug"] = slugify(SLUG_TRANSLITERATOR(self.cleaned_data["name"])) + return self.cleaned_data["slug"][:50] def clean(self): @@ -107,72 +112,71 @@ class CategoryBaseAdminForm(forms.ModelForm): # Validate slug is valid in that level kwargs = {} - if self.cleaned_data.get('parent', None) is None: - kwargs['parent__isnull'] = True + if self.cleaned_data.get("parent", None) is None: + kwargs["parent__isnull"] = True else: - kwargs['parent__pk'] = int(self.cleaned_data['parent'].id) - this_level_slugs = [c['slug'] for c in opts.model.objects.filter(**kwargs).values('id', 'slug') if c['id'] != self.instance.id] - if self.cleaned_data['slug'] in this_level_slugs: - raise forms.ValidationError(_('The slug must be unique among ' - 'the items at its level.')) + kwargs["parent__pk"] = int(self.cleaned_data["parent"].id) + this_level_slugs = [ + c["slug"] for c in opts.model.objects.filter(**kwargs).values("id", "slug") if c["id"] != self.instance.id + ] + if self.cleaned_data["slug"] in this_level_slugs: + raise forms.ValidationError(_("The slug must be unique among " "the items at its level.")) # Validate Category Parent # Make sure the category doesn't set itself or any of its children as # its parent. - if self.cleaned_data.get('parent', None) is None or self.instance.id is None: + if self.cleaned_data.get("parent", None) is None or self.instance.id is None: return self.cleaned_data if self.instance.pk: - decendant_ids = self.instance.get_descendants().values_list('id', flat=True) + decendant_ids = self.instance.get_descendants().values_list("id", flat=True) else: decendant_ids = [] - if self.cleaned_data['parent'].id == self.instance.id: - raise forms.ValidationError(_("You can't set the parent of the " - "item to itself.")) - elif self.cleaned_data['parent'].id in decendant_ids: - raise forms.ValidationError(_("You can't set the parent of the " - "item to a descendant.")) + if self.cleaned_data["parent"].id == self.instance.id: + raise forms.ValidationError(_("You can't set the parent of the " "item to itself.")) + elif self.cleaned_data["parent"].id in decendant_ids: + raise forms.ValidationError(_("You can't set the parent of the " "item to a descendant.")) return self.cleaned_data class CategoryBaseAdmin(TreeEditor, admin.ModelAdmin): form = CategoryBaseAdminForm - list_display = ('name', 'active') - search_fields = ('name',) - prepopulated_fields = {'slug': ('name',)} + list_display = ("name", "active") + search_fields = ("name",) + prepopulated_fields = {"slug": ("name",)} - actions = ['activate', 'deactivate'] + actions = ["activate", "deactivate"] def get_actions(self, request): actions = super(CategoryBaseAdmin, self).get_actions(request) - if 'delete_selected' in actions: - del actions['delete_selected'] + if "delete_selected" in actions: + del actions["delete_selected"] return actions def deactivate(self, request, queryset): """ Set active to False for selected items """ - selected_cats = self.model.objects.filter( - pk__in=[int(x) for x in request.POST.getlist('_selected_action')]) + selected_cats = self.model.objects.filter(pk__in=[int(x) for x in request.POST.getlist("_selected_action")]) for item in selected_cats: if item.active: item.active = False item.save() item.children.all().update(active=False) - deactivate.short_description = _('Deactivate selected categories and their children') + + deactivate.short_description = _("Deactivate selected categories and their children") def activate(self, request, queryset): """ Set active to True for selected items """ - selected_cats = self.model.objects.filter( - pk__in=[int(x) for x in request.POST.getlist('_selected_action')]) + selected_cats = self.model.objects.filter(pk__in=[int(x) for x in request.POST.getlist("_selected_action")]) for item in selected_cats: item.active = True item.save() item.children.all().update(active=True) - activate.short_description = _('Activate selected categories and their children') + + activate.short_description = _("Activate selected categories and their children") diff --git a/categories/editor/settings.py b/categories/editor/settings.py index af293e5..5ea2e61 100644 --- a/categories/editor/settings.py +++ b/categories/editor/settings.py @@ -1,13 +1,13 @@ -from django.conf import settings import django +from django.conf import settings DJANGO10_COMPAT = django.VERSION[0] < 1 or (django.VERSION[0] == 1 and django.VERSION[1] < 1) -STATIC_URL = getattr(settings, 'STATIC_URL', settings.MEDIA_URL) +STATIC_URL = getattr(settings, "STATIC_URL", settings.MEDIA_URL) if STATIC_URL is None: STATIC_URL = settings.MEDIA_URL -MEDIA_PATH = getattr(settings, 'EDITOR_MEDIA_PATH', '%seditor/' % STATIC_URL) +MEDIA_PATH = getattr(settings, "EDITOR_MEDIA_PATH", "%seditor/" % STATIC_URL) -TREE_INITIAL_STATE = getattr(settings, 'EDITOR_TREE_INITIAL_STATE', 'collapsed') +TREE_INITIAL_STATE = getattr(settings, "EDITOR_TREE_INITIAL_STATE", "collapsed") -IS_GRAPPELLI_INSTALLED = 'grappelli' in settings.INSTALLED_APPS +IS_GRAPPELLI_INSTALLED = "grappelli" in settings.INSTALLED_APPS diff --git a/categories/editor/static/editor/jquery.treeTable.css b/categories/editor/static/editor/jquery.treeTable.css index 9d9a263..07421f1 100644 --- a/categories/editor/static/editor/jquery.treeTable.css +++ b/categories/editor/static/editor/jquery.treeTable.css @@ -66,4 +66,4 @@ .treeTable .ui-draggable-dragging { color: #000; z-index: 1; -} \ No newline at end of file +} diff --git a/categories/editor/static/editor/jquery.treeTable.js b/categories/editor/static/editor/jquery.treeTable.js index 38f7bcb..ea2a88b 100644 --- a/categories/editor/static/editor/jquery.treeTable.js +++ b/categories/editor/static/editor/jquery.treeTable.js @@ -460,4 +460,4 @@ function parentOf(node) { return $(node).parentOf(); } -})(django.jQuery); \ No newline at end of file +})(django.jQuery); diff --git a/categories/editor/templates/admin/editor/grappelli_tree_list_results.html b/categories/editor/templates/admin/editor/grappelli_tree_list_results.html index 379471e..f5b5e5b 100644 --- a/categories/editor/templates/admin/editor/grappelli_tree_list_results.html +++ b/categories/editor/templates/admin/editor/grappelli_tree_list_results.html @@ -25,4 +25,4 @@ -{% endif %} \ No newline at end of file +{% endif %} diff --git a/categories/editor/templates/admin/editor/tree_editor.html b/categories/editor/templates/admin/editor/tree_editor.html index 9179640..337da05 100644 --- a/categories/editor/templates/admin/editor/tree_editor.html +++ b/categories/editor/templates/admin/editor/tree_editor.html @@ -36,4 +36,4 @@ {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %} {% result_tree_list cl %} {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/editor/templatetags/admin_tree_list_tags.py b/categories/editor/templatetags/admin_tree_list_tags.py index 6ef6e95..160752b 100644 --- a/categories/editor/templatetags/admin_tree_list_tags.py +++ b/categories/editor/templatetags/admin_tree_list_tags.py @@ -1,29 +1,30 @@ import django +from django.contrib.admin.templatetags.admin_list import _boolean_icon, result_headers +from django.contrib.admin.utils import lookup_field +from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.template import Library -from django.contrib.admin.templatetags.admin_list import result_headers, _boolean_icon -from django.contrib.admin.utils import lookup_field -from categories.editor.utils import display_for_field -from django.core.exceptions import ObjectDoesNotExist -from django.utils.encoding import smart_text, force_text -from django.utils.html import escape, conditional_escape, escapejs, format_html +from django.utils.encoding import force_text, smart_text +from django.utils.html import conditional_escape, escape, escapejs, format_html from django.utils.safestring import mark_safe from categories.editor import settings +from categories.editor.utils import display_for_field register = Library() -TREE_LIST_RESULTS_TEMPLATE = 'admin/editor/tree_list_results.html' +TREE_LIST_RESULTS_TEMPLATE = "admin/editor/tree_list_results.html" if settings.IS_GRAPPELLI_INSTALLED: - TREE_LIST_RESULTS_TEMPLATE = 'admin/editor/grappelli_tree_list_results.html' + TREE_LIST_RESULTS_TEMPLATE = "admin/editor/grappelli_tree_list_results.html" def get_empty_value_display(cl): - if hasattr(cl.model_admin, 'get_empty_value_display'): + if hasattr(cl.model_admin, "get_empty_value_display"): return cl.model_admin.get_empty_value_display() else: # Django < 1.9 from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE + return EMPTY_CHANGELIST_VALUE @@ -34,7 +35,7 @@ def items_for_tree_result(cl, result, form): first = True pk = cl.lookup_opts.pk.attname for field_name in cl.list_display: - row_class = '' + row_class = "" try: f, attr, value = lookup_field(field_name, result, cl.model_admin) except (AttributeError, ObjectDoesNotExist): @@ -42,10 +43,10 @@ def items_for_tree_result(cl, result, form): else: if f is None: if django.VERSION[0] == 1 and django.VERSION[1] == 4: - if field_name == 'action_checkbox': + if field_name == "action_checkbox": row_class = ' class="action-checkbox disclosure"' - allow_tags = getattr(attr, 'allow_tags', False) - boolean = getattr(attr, 'boolean', False) + allow_tags = getattr(attr, "allow_tags", False) + boolean = getattr(attr, "boolean", False) if boolean: allow_tags = True result_repr = _boolean_icon(value) @@ -60,16 +61,16 @@ def items_for_tree_result(cl, result, form): else: if value is None: result_repr = get_empty_value_display(cl) - if hasattr(f, 'rel') and isinstance(f.rel, models.ManyToOneRel): + if hasattr(f, "rel") and isinstance(f.rel, models.ManyToOneRel): result_repr = escape(getattr(result, f.name)) else: - result_repr = display_for_field(value, f, '') + result_repr = display_for_field(value, f, "") if isinstance(f, models.DateField) or isinstance(f, models.TimeField): row_class = ' class="nowrap"' if first: if django.VERSION[0] == 1 and django.VERSION[1] < 4: try: - f, attr, checkbox_value = lookup_field('action_checkbox', result, cl.model_admin) + f, attr, checkbox_value = lookup_field("action_checkbox", result, cl.model_admin) if row_class: row_class = "%s%s" % (row_class[:-1], ' disclosure"') else: @@ -77,14 +78,14 @@ def items_for_tree_result(cl, result, form): except (AttributeError, ObjectDoesNotExist): pass - if force_text(result_repr) == '': - result_repr = mark_safe(' ') + if force_text(result_repr) == "": + result_repr = mark_safe(" ") # If list_display_links not defined, add the link tag to the first field if (first and not cl.list_display_links) or field_name in cl.list_display_links: if django.VERSION[0] == 1 and django.VERSION[1] < 4: - table_tag = 'td' # {True:'th', False:'td'}[first] + table_tag = "td" # {True:'th', False:'td'}[first] else: - table_tag = {True: 'th', False: 'td'}[first] + table_tag = {True: "th", False: "td"}[first] url = cl.url_for_result(result) # Convert the pk to something that can be used in Javascript. @@ -104,9 +105,14 @@ def items_for_tree_result(cl, result, form): row_class, url, format_html( - ' onclick="opener.dismissRelatedLookupPopup(window, ' - ''{}'); return false;"', result_id - ) if cl.is_popup else '', result_repr, table_tag) + ' onclick="opener.dismissRelatedLookupPopup(window, ' ''{}'); return false;"', + result_id, + ) + if cl.is_popup + else "", + result_repr, + table_tag, + ) ) else: @@ -118,9 +124,9 @@ def items_for_tree_result(cl, result, form): result_repr = mark_safe(force_text(bf.errors) + force_text(bf)) else: result_repr = conditional_escape(result_repr) - yield mark_safe(smart_text('%s' % (row_class, result_repr))) + yield mark_safe(smart_text("%s" % (row_class, result_repr))) if form and not form[cl.model._meta.pk.name].is_hidden: - yield mark_safe(smart_text('%s' % force_text(form[cl.model._meta.pk.name]))) + yield mark_safe(smart_text("%s" % force_text(form[cl.model._meta.pk.name]))) class TreeList(list): @@ -131,7 +137,7 @@ def tree_results(cl): if cl.formset: for res, form in zip(cl.result_list, cl.formset.forms): result = TreeList(items_for_tree_result(cl, res, form)) - if hasattr(res, 'pk'): + if hasattr(res, "pk"): result.pk = res.pk if res.parent: result.parent_pk = res.parent.pk @@ -141,7 +147,7 @@ def tree_results(cl): else: for res in cl.result_list: result = TreeList(items_for_tree_result(cl, res, None)) - if hasattr(res, 'pk'): + if hasattr(res, "pk"): result.pk = res.pk if res.parent: result.parent_pk = res.parent.pk @@ -155,14 +161,12 @@ def result_tree_list(cl): Displays the headers and data list together """ import django - result = { - 'cl': cl, - 'result_headers': list(result_headers(cl)), - 'results': list(tree_results(cl)) - } + + result = {"cl": cl, "result_headers": list(result_headers(cl)), "results": list(tree_results(cl))} if django.VERSION[0] == 1 and django.VERSION[1] > 2: from django.contrib.admin.templatetags.admin_list import result_hidden_fields - result['result_hidden_fields'] = list(result_hidden_fields(cl)) + + result["result_hidden_fields"] = list(result_hidden_fields(cl)) return result diff --git a/categories/editor/tree_editor.py b/categories/editor/tree_editor.py index f832df5..45c70d1 100644 --- a/categories/editor/tree_editor.py +++ b/categories/editor/tree_editor.py @@ -1,12 +1,11 @@ -from django.contrib import admin -from django.db.models.query import QuerySet -from django.contrib.admin.views.main import ChangeList -from django.http import HttpResponseRedirect -from django.utils.translation import ugettext_lazy as _ -from django.contrib.admin.options import IncorrectLookupParameters -from django.shortcuts import render - import django +from django.contrib import admin +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib.admin.views.main import ChangeList +from django.db.models.query import QuerySet +from django.http import HttpResponseRedirect +from django.shortcuts import render +from django.utils.translation import ugettext_lazy as _ from . import settings @@ -24,6 +23,7 @@ class TreeEditorQuerySet(QuerySet): in the result set, so the resulting tree display actually makes sense. """ + def iterator(self): qs = self # Reaching into the bowels of query sets to find out whether the qs is @@ -36,9 +36,9 @@ class TreeEditorQuerySet(QuerySet): # this cuts down the number of queries considerably since all ancestors # will already be in include_pages when they are checked, thus not # trigger additional queries. - for p in super(TreeEditorQuerySet, self.order_by('rght')).iterator(): + for p in super(TreeEditorQuerySet, self.order_by("rght")).iterator(): if p.parent_id and p.parent_id not in include_pages and p.id not in include_pages: - ancestor_id_list = p.get_ancestors().values_list('id', flat=True) + ancestor_id_list = p.get_ancestors().values_list("id", flat=True) include_pages.update(ancestor_id_list) if include_pages: @@ -68,18 +68,18 @@ class TreeEditorQuerySet(QuerySet): class TreeChangeList(ChangeList): def _get_default_ordering(self): if django.VERSION[0] == 1 and django.VERSION[1] < 4: - return '', '' # ('tree_id', 'lft') + return "", "" # ('tree_id', 'lft') else: return [] def get_ordering(self, request=None, queryset=None): if django.VERSION[0] == 1 and django.VERSION[1] < 4: - return '', '' # ('tree_id', 'lft') + return "", "" # ('tree_id', 'lft') else: return [] def get_queryset(self, *args, **kwargs): - qs = super(TreeChangeList, self).get_queryset(*args, **kwargs).order_by('tree_id', 'lft') + qs = super(TreeChangeList, self).get_queryset(*args, **kwargs).order_by("tree_id", "lft") return qs @@ -88,18 +88,18 @@ class TreeEditor(admin.ModelAdmin): list_max_show_all = 200 # new in django 1.4 class Media: - css = {'all': (settings.MEDIA_PATH + "jquery.treeTable.css", )} + css = {"all": (settings.MEDIA_PATH + "jquery.treeTable.css",)} js = [] - js.extend((settings.MEDIA_PATH + "jquery.treeTable.js", )) + js.extend((settings.MEDIA_PATH + "jquery.treeTable.js",)) def __init__(self, *args, **kwargs): super(TreeEditor, self).__init__(*args, **kwargs) self.list_display = list(self.list_display) - if 'action_checkbox' in self.list_display: - self.list_display.remove('action_checkbox') + if "action_checkbox" in self.list_display: + self.list_display.remove("action_checkbox") opts = self.model._meta @@ -108,9 +108,9 @@ class TreeEditor(admin.ModelAdmin): grappelli_prefix = "grappelli_" self.change_list_template = [ - 'admin/%s/%s/editor/%stree_editor.html' % (opts.app_label, opts.object_name.lower(), grappelli_prefix), - 'admin/%s/editor/%stree_editor.html' % (opts.app_label, grappelli_prefix), - 'admin/editor/%stree_editor.html' % grappelli_prefix, + "admin/%s/%s/editor/%stree_editor.html" % (opts.app_label, opts.object_name.lower(), grappelli_prefix), + "admin/%s/editor/%stree_editor.html" % (opts.app_label, grappelli_prefix), + "admin/editor/%stree_editor.html" % grappelli_prefix, ] def get_changelist(self, request, **kwargs): @@ -125,6 +125,7 @@ class TreeEditor(admin.ModelAdmin): from django.core.exceptions import PermissionDenied from django.utils.encoding import force_text from django.utils.translation import ungettext + opts = self.model._meta app_label = opts.app_label if not self.has_change_permission(request, None): @@ -137,31 +138,56 @@ class TreeEditor(admin.ModelAdmin): list_display = list(self.list_display) if not actions: try: - list_display.remove('action_checkbox') + list_display.remove("action_checkbox") except ValueError: pass try: if django.VERSION[0] == 1 and django.VERSION[1] < 4: params = ( - request, self.model, list_display, - self.list_display_links, self.list_filter, self.date_hierarchy, - self.search_fields, self.list_select_related, - self.list_per_page, self.list_editable, self) + request, + self.model, + list_display, + self.list_display_links, + self.list_filter, + self.date_hierarchy, + self.search_fields, + self.list_select_related, + self.list_per_page, + self.list_editable, + self, + ) elif django.VERSION[0] == 1 or (django.VERSION[0] == 2 and django.VERSION[1] < 1): params = ( - request, self.model, list_display, - self.list_display_links, self.list_filter, self.date_hierarchy, - self.search_fields, self.list_select_related, - self.list_per_page, self.list_max_show_all, - self.list_editable, self) + request, + self.model, + list_display, + self.list_display_links, + self.list_filter, + self.date_hierarchy, + self.search_fields, + self.list_select_related, + self.list_per_page, + self.list_max_show_all, + self.list_editable, + self, + ) else: params = ( - request, self.model, list_display, - self.list_display_links, self.list_filter, self.date_hierarchy, - self.search_fields, self.list_select_related, - self.list_per_page, self.list_max_show_all, - self.list_editable, self, self.sortable_by) + request, + self.model, + list_display, + self.list_display_links, + self.list_filter, + self.date_hierarchy, + self.search_fields, + self.list_select_related, + self.list_per_page, + self.list_max_show_all, + self.list_editable, + self, + self.sortable_by, + ) cl = TreeChangeList(*params) except IncorrectLookupParameters: # Wacky lookup parameters were given, so redirect to the main @@ -170,15 +196,13 @@ class TreeEditor(admin.ModelAdmin): # the 'invalid=1' parameter was already in the query string, something # is screwed up with the database, so display an error page. if ERROR_FLAG in list(request.GET.keys()): - return render( - request, - 'admin/invalid_setup.html', {'title': _('Database error')}) - return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') + return render(request, "admin/invalid_setup.html", {"title": _("Database error")}) + return HttpResponseRedirect(request.path + "?" + ERROR_FLAG + "=1") # If the request was POSTed, this might be a bulk action or a bulk edit. # Try to look up an action first, but if this isn't an action the POST # will fall through to the bulk edit check, below. - if actions and request.method == 'POST': + if actions and request.method == "POST": response = self.response_action(request, queryset=cl.get_queryset()) if response: return response @@ -191,9 +215,7 @@ class TreeEditor(admin.ModelAdmin): # Handle POSTed bulk-edit data. if request.method == "POST" and self.list_editable: FormSet = self.get_changelist_formset(request) - formset = cl.formset = FormSet( - request.POST, request.FILES, queryset=cl.result_list - ) + formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list) if formset.is_valid(): changecount = 0 for form in formset.forms: @@ -213,9 +235,8 @@ class TreeEditor(admin.ModelAdmin): msg = ungettext( "%(count)s %(name)s was changed successfully.", "%(count)s %(name)s were changed successfully.", - changecount) % {'count': changecount, - 'name': name, - 'obj': force_text(obj)} + changecount, + ) % {"count": changecount, "name": name, "obj": force_text(obj)} self.message_user(request, msg) return HttpResponseRedirect(request.get_full_path()) @@ -234,40 +255,47 @@ class TreeEditor(admin.ModelAdmin): # Build the action form and populate it with available actions. if actions: action_form = self.action_form(auto_id=None) - action_form.fields['action'].choices = self.get_action_choices(request) + action_form.fields["action"].choices = self.get_action_choices(request) else: action_form = None context = { - 'title': cl.title, - 'is_popup': cl.is_popup, - 'cl': cl, - 'media': media, - 'has_add_permission': self.has_add_permission(request), - 'app_label': app_label, - 'action_form': action_form, - 'actions_on_top': self.actions_on_top, - 'actions_on_bottom': self.actions_on_bottom, + "title": cl.title, + "is_popup": cl.is_popup, + "cl": cl, + "media": media, + "has_add_permission": self.has_add_permission(request), + "app_label": app_label, + "action_form": action_form, + "actions_on_top": self.actions_on_top, + "actions_on_bottom": self.actions_on_bottom, } if django.VERSION[0] == 1 and django.VERSION[1] < 4: - context['root_path'] = self.admin_site.root_path + context["root_path"] = self.admin_site.root_path elif django.VERSION[0] == 1 or (django.VERSION[0] == 2 and django.VERSION[1] < 1): - selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', cl.result_count) + selection_note_all = ungettext("%(total_count)s selected", "All %(total_count)s selected", cl.result_count) - context.update({ - 'module_name': force_text(opts.verbose_name_plural), - 'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)}, - 'selection_note_all': selection_note_all % {'total_count': cl.result_count}, - }) + context.update( + { + "module_name": force_text(opts.verbose_name_plural), + "selection_note": _("0 of %(cnt)s selected") % {"cnt": len(cl.result_list)}, + "selection_note_all": selection_note_all % {"total_count": cl.result_count}, + } + ) else: - context['opts'] = self.model._meta + context["opts"] = self.model._meta context.update(extra_context or {}) - return render(request, self.change_list_template or [ - 'admin/%s/%s/change_list.html' % (app_label, opts.object_name.lower()), - 'admin/%s/change_list.html' % app_label, - 'admin/change_list.html' - ], context=context) + return render( + request, + self.change_list_template + or [ + "admin/%s/%s/change_list.html" % (app_label, opts.object_name.lower()), + "admin/%s/change_list.html" % app_label, + "admin/change_list.html", + ], + context=context, + ) def changelist_view(self, request, extra_context=None, *args, **kwargs): """ @@ -275,8 +303,8 @@ class TreeEditor(admin.ModelAdmin): change list/actions page. """ extra_context = extra_context or {} - extra_context['EDITOR_MEDIA_PATH'] = settings.MEDIA_PATH - extra_context['EDITOR_TREE_INITIAL_STATE'] = settings.TREE_INITIAL_STATE + extra_context["EDITOR_MEDIA_PATH"] = settings.MEDIA_PATH + extra_context["EDITOR_TREE_INITIAL_STATE"] = settings.TREE_INITIAL_STATE # FIXME return self.old_changelist_view(request, extra_context) diff --git a/categories/fields.py b/categories/fields.py index 1926de9..719b72e 100644 --- a/categories/fields.py +++ b/categories/fields.py @@ -4,21 +4,24 @@ from django.db.models import ForeignKey, ManyToManyField class CategoryM2MField(ManyToManyField): def __init__(self, **kwargs): from .models import Category - if 'to' in kwargs: - kwargs.pop('to') + + if "to" in kwargs: + kwargs.pop("to") super(CategoryM2MField, self).__init__(to=Category, **kwargs) class CategoryFKField(ForeignKey): def __init__(self, **kwargs): from .models import Category - if 'to' in kwargs: - kwargs.pop('to') + + if "to" in kwargs: + kwargs.pop("to") super(CategoryFKField, self).__init__(to=Category, **kwargs) try: from south.modelsinspector import add_introspection_rules + add_introspection_rules([], [r"^categories\.fields\.CategoryFKField"]) add_introspection_rules([], [r"^categories\.fields\.CategoryM2MField"]) except ImportError: diff --git a/categories/fixtures/musicgenres.json b/categories/fixtures/musicgenres.json index b832884..3817510 100644 --- a/categories/fixtures/musicgenres.json +++ b/categories/fixtures/musicgenres.json @@ -4414,4 +4414,4 @@ } } -] \ No newline at end of file +] diff --git a/categories/fixtures/test_category_spaces.txt b/categories/fixtures/test_category_spaces.txt index 025edbe..85852b5 100644 --- a/categories/fixtures/test_category_spaces.txt +++ b/categories/fixtures/test_category_spaces.txt @@ -5,4 +5,4 @@ Category 2 Category 2-1 Category 2-1-1 Category 3 - Category 3-1 \ No newline at end of file + Category 3-1 diff --git a/categories/fixtures/test_category_tabs.txt b/categories/fixtures/test_category_tabs.txt index 207a634..8ded421 100644 --- a/categories/fixtures/test_category_tabs.txt +++ b/categories/fixtures/test_category_tabs.txt @@ -5,4 +5,4 @@ Category 2 Category 2-1 Category 2-1-1 Category 3 - Category 3-1 \ No newline at end of file + Category 3-1 diff --git a/categories/genericcollection.py b/categories/genericcollection.py index ffa01a0..1745914 100644 --- a/categories/genericcollection.py +++ b/categories/genericcollection.py @@ -1,7 +1,8 @@ +import json + from django.contrib import admin from django.contrib.contenttypes.models import ContentType -from django.urls import reverse, NoReverseMatch -import json +from django.urls import NoReverseMatch, reverse class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): @@ -9,7 +10,7 @@ class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): ct_fk_field = "object_id" def get_content_types(self): - ctypes = ContentType.objects.all().order_by('id').values_list('id', 'app_label', 'model') + ctypes = ContentType.objects.all().order_by("id").values_list("id", "app_label", "model") elements = {} for x, y, z in ctypes: try: @@ -25,12 +26,12 @@ class GenericCollectionInlineModelAdmin(admin.options.InlineModelAdmin): return result class Media: - js = ('contentrelations/js/genericlookup.js', ) + js = ("contentrelations/js/genericlookup.js",) class GenericCollectionTabularInline(GenericCollectionInlineModelAdmin): - template = 'admin/edit_inline/gen_coll_tabular.html' + template = "admin/edit_inline/gen_coll_tabular.html" class GenericCollectionStackedInline(GenericCollectionInlineModelAdmin): - template = 'admin/edit_inline/gen_coll_stacked.html' + template = "admin/edit_inline/gen_coll_stacked.html" diff --git a/categories/locale/it/LC_MESSAGES/django.po b/categories/locale/it/LC_MESSAGES/django.po index 1186eef..32f3f2d 100644 --- a/categories/locale/it/LC_MESSAGES/django.po +++ b/categories/locale/it/LC_MESSAGES/django.po @@ -181,4 +181,3 @@ msgstr "Cancella?" #: templates/admin/edit_inline/gen_coll_tabular.html:24 msgid "View on site" msgstr "Vedi sul sito" - diff --git a/categories/management/commands/add_category_fields.py b/categories/management/commands/add_category_fields.py index 4d44c4d..377f5e5 100644 --- a/categories/management/commands/add_category_fields.py +++ b/categories/management/commands/add_category_fields.py @@ -5,13 +5,14 @@ class Command(BaseCommand): """ Alter one or more models' tables with the registered attributes """ + help = "Alter the tables for all registered models, or just specified models" args = "[appname ...]" can_import_settings = True requires_system_checks = False def add_arguments(self, parser): - parser.add_argument('app_names', nargs='*') + parser.add_argument("app_names", nargs="*") def handle(self, *args, **options): """ @@ -20,8 +21,9 @@ class Command(BaseCommand): from categories.migration import migrate_app from categories.settings import MODEL_REGISTRY - if options['app_names']: - for app in options['app_names']: + + if options["app_names"]: + for app in options["app_names"]: migrate_app(None, app) else: for app in MODEL_REGISTRY: diff --git a/categories/management/commands/drop_category_field.py b/categories/management/commands/drop_category_field.py index cc4850e..f10a220 100644 --- a/categories/management/commands/drop_category_field.py +++ b/categories/management/commands/drop_category_field.py @@ -1,27 +1,28 @@ -from django.core.management.base import BaseCommand -from django.core.management.base import CommandError +from django.core.management.base import BaseCommand, CommandError class Command(BaseCommand): """ Alter one or more models' tables with the registered attributes """ + help = "Drop the given field from the given model's table" args = "appname modelname fieldname" can_import_settings = True requires_system_checks = False def add_arguments(self, parser): - parser.add_argument('app_name') - parser.add_argument('model_name') - parser.add_argument('field_name') + parser.add_argument("app_name") + parser.add_argument("model_name") + parser.add_argument("field_name") def handle(self, *args, **options): """ Alter the tables """ from categories.migration import drop_field - if 'app_name' not in options or 'model_name' not in options or 'field_name' not in options: + + if "app_name" not in options or "model_name" not in options or "field_name" not in options: raise CommandError("You must specify an Application name, a Model name and a Field name") - drop_field(options['app_name'], options['model_name'], options['field_name']) + drop_field(options["app_name"], options["model_name"], options["field_name"]) diff --git a/categories/management/commands/import_categories.py b/categories/management/commands/import_categories.py index a899e50..6009afb 100644 --- a/categories/management/commands/import_categories.py +++ b/categories/management/commands/import_categories.py @@ -1,6 +1,5 @@ from django.core.management.base import BaseCommand, CommandError from django.db import transaction - from slugify import slugify from categories.models import Category @@ -10,7 +9,9 @@ from categories.settings import SLUG_TRANSLITERATOR class Command(BaseCommand): """Import category trees from a file.""" - help = "Imports category tree(s) from a file. Sub categories must be indented by the same multiple of spaces or tabs." + help = ( + "Imports category tree(s) from a file. Sub categories must be indented by the same multiple of spaces or tabs." + ) args = "file_path [file_path ...]" def get_indent(self, string): @@ -19,13 +20,13 @@ class Command(BaseCommand): """ indent_amt = 0 - if string[0] == '\t': - return '\t' + if string[0] == "\t": + return "\t" for char in string: - if char == ' ': + if char == " ": indent_amt += 1 else: - return ' ' * indent_amt + return " " * indent_amt @transaction.atomic def make_category(self, string, parent=None, order=1): @@ -36,9 +37,9 @@ class Command(BaseCommand): name=string.strip(), slug=slugify(SLUG_TRANSLITERATOR(string.strip()))[:49], # arent=parent, - order=order + order=order, ) - cat._tree_manager.insert_node(cat, parent, 'last-child', True) + cat._tree_manager.insert_node(cat, parent, "last-child", True) cat.save() if parent: parent.rght = cat.rght + 1 @@ -49,10 +50,10 @@ class Command(BaseCommand): """ Do the work of parsing each line """ - indent = '' + indent = "" level = 0 - if lines[0][0] == ' ' or lines[0][0] == '\t': + if lines[0][0] == " " or lines[0][0] == "\t": raise CommandError("The first line in the file cannot start with a space or tab.") # This keeps track of the current parents at a given level @@ -61,8 +62,8 @@ class Command(BaseCommand): for line in lines: if len(line) == 0: continue - if line[0] == ' ' or line[0] == '\t': - if indent == '': + if line[0] == " " or line[0] == "\t": + if indent == "": indent = self.get_indent(line) elif not line[0] in indent: raise CommandError("You can't mix spaces and tabs for indents") @@ -83,7 +84,7 @@ class Command(BaseCommand): if not os.path.isfile(file_path): print("File %s not found." % file_path) continue - f = open(file_path, 'r') + f = open(file_path, "r") data = f.readlines() f.close() diff --git a/categories/migration.py b/categories/migration.py index 407a796..77358a5 100644 --- a/categories/migration.py +++ b/categories/migration.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- -from django.db import connection, transaction from django.apps import apps +from django.db import connection, transaction from django.db.utils import ProgrammingError @@ -25,7 +24,7 @@ def field_exists(app_name, model_name, field_name): # Return True if the many to many table exists field = model._meta.get_field(field_name) - if hasattr(field, 'm2m_db_table'): + if hasattr(field, "m2m_db_table"): m2m_table_name = field.m2m_db_table() m2m_field_info = connection.introspection.get_table_description(cursor, m2m_table_name) if m2m_field_info: @@ -50,9 +49,10 @@ def migrate_app(sender, *args, **kwargs): Migrate all models of this app registered """ from .registration import registry - if 'app_config' not in kwargs: + + if "app_config" not in kwargs: return - app_config = kwargs['app_config'] + app_config = kwargs["app_config"] app_name = app_config.label @@ -60,7 +60,7 @@ def migrate_app(sender, *args, **kwargs): sid = transaction.savepoint() for fld in fields: - model_name, field_name = fld.split('.')[1:] + model_name, field_name = fld.split(".")[1:] if field_exists(app_name, model_name, field_name): continue model = app_config.get_model(model_name) diff --git a/categories/migrations/0001_initial.py b/categories/migrations/0001_initial.py index b58fabc..883fd62 100644 --- a/categories/migrations/0001_initial.py +++ b/categories/migrations/0001_initial.py @@ -1,59 +1,123 @@ -# -*- coding: utf-8 -*- -from django.db import models, migrations import django.core.files.storage import mptt.fields +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('contenttypes', '0001_initial'), + ("contenttypes", "0001_initial"), ] operations = [ migrations.CreateModel( - name='Category', + name="Category", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=100, verbose_name='name')), - ('slug', models.SlugField(verbose_name='slug')), - ('active', models.BooleanField(default=True, verbose_name='active')), - ('thumbnail', models.FileField(storage=django.core.files.storage.FileSystemStorage(), null=True, upload_to='uploads/categories/thumbnails', blank=True)), - ('thumbnail_width', models.IntegerField(null=True, blank=True)), - ('thumbnail_height', models.IntegerField(null=True, blank=True)), - ('order', models.IntegerField(default=0)), - ('alternate_title', models.CharField(default='', help_text='An alternative title to use on pages with this category.', max_length=100, blank=True)), - ('alternate_url', models.CharField(help_text='An alternative URL to use instead of the one derived from the category hierarchy.', max_length=200, blank=True)), - ('description', models.TextField(null=True, blank=True)), - ('meta_keywords', models.CharField(default='', help_text='Comma-separated keywords for search engines.', max_length=255, blank=True)), - ('meta_extra', models.TextField(default='', help_text='(Advanced) Any additional HTML to be placed verbatim in the <head>', blank=True)), - ('lft', models.PositiveIntegerField(editable=False, db_index=True)), - ('rght', models.PositiveIntegerField(editable=False, db_index=True)), - ('tree_id', models.PositiveIntegerField(editable=False, db_index=True)), - ('level', models.PositiveIntegerField(editable=False, db_index=True)), - ('parent', mptt.fields.TreeForeignKey(related_name='children', verbose_name='parent', blank=True, to='categories.Category', on_delete=models.CASCADE, null=True)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("name", models.CharField(max_length=100, verbose_name="name")), + ("slug", models.SlugField(verbose_name="slug")), + ("active", models.BooleanField(default=True, verbose_name="active")), + ( + "thumbnail", + models.FileField( + storage=django.core.files.storage.FileSystemStorage(), + null=True, + upload_to="uploads/categories/thumbnails", + blank=True, + ), + ), + ("thumbnail_width", models.IntegerField(null=True, blank=True)), + ("thumbnail_height", models.IntegerField(null=True, blank=True)), + ("order", models.IntegerField(default=0)), + ( + "alternate_title", + models.CharField( + default="", + help_text="An alternative title to use on pages with this category.", + max_length=100, + blank=True, + ), + ), + ( + "alternate_url", + models.CharField( + help_text="An alternative URL to use instead of the one derived from the category hierarchy.", + max_length=200, + blank=True, + ), + ), + ("description", models.TextField(null=True, blank=True)), + ( + "meta_keywords", + models.CharField( + default="", + help_text="Comma-separated keywords for search engines.", + max_length=255, + blank=True, + ), + ), + ( + "meta_extra", + models.TextField( + default="", + help_text="(Advanced) Any additional HTML to be placed verbatim in the <head>", + blank=True, + ), + ), + ("lft", models.PositiveIntegerField(editable=False, db_index=True)), + ("rght", models.PositiveIntegerField(editable=False, db_index=True)), + ("tree_id", models.PositiveIntegerField(editable=False, db_index=True)), + ("level", models.PositiveIntegerField(editable=False, db_index=True)), + ( + "parent", + mptt.fields.TreeForeignKey( + related_name="children", + verbose_name="parent", + blank=True, + to="categories.Category", + on_delete=models.CASCADE, + null=True, + ), + ), ], options={ - 'ordering': ('tree_id', 'lft'), - 'abstract': False, - 'verbose_name': 'category', - 'verbose_name_plural': 'categories', + "ordering": ("tree_id", "lft"), + "abstract": False, + "verbose_name": "category", + "verbose_name_plural": "categories", }, ), migrations.CreateModel( - name='CategoryRelation', + name="CategoryRelation", fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('object_id', models.PositiveIntegerField(verbose_name='object id')), - ('relation_type', models.CharField(help_text="A generic text field to tag a relation, like 'leadphoto'.", max_length='200', null=True, verbose_name='relation type', blank=True)), - ('category', models.ForeignKey(verbose_name='category', to='categories.Category', on_delete=models.CASCADE)), - ('content_type', models.ForeignKey(verbose_name='content type', to='contenttypes.ContentType', on_delete=models.CASCADE)), + ("id", models.AutoField(verbose_name="ID", serialize=False, auto_created=True, primary_key=True)), + ("object_id", models.PositiveIntegerField(verbose_name="object id")), + ( + "relation_type", + models.CharField( + help_text="A generic text field to tag a relation, like 'leadphoto'.", + max_length="200", + null=True, + verbose_name="relation type", + blank=True, + ), + ), + ( + "category", + models.ForeignKey(verbose_name="category", to="categories.Category", on_delete=models.CASCADE), + ), + ( + "content_type", + models.ForeignKey( + verbose_name="content type", to="contenttypes.ContentType", on_delete=models.CASCADE + ), + ), ], ), migrations.AlterUniqueTogether( - name='category', - unique_together=set([('parent', 'name')]), + name="category", + unique_together=set([("parent", "name")]), ), ] diff --git a/categories/migrations/0002_auto_20170217_1111.py b/categories/migrations/0002_auto_20170217_1111.py index 27b77ed..38c1f4f 100644 --- a/categories/migrations/0002_auto_20170217_1111.py +++ b/categories/migrations/0002_auto_20170217_1111.py @@ -1,27 +1,32 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-02-17 11:11 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.manager +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('categories', '0001_initial'), + ("categories", "0001_initial"), ] operations = [ migrations.AlterModelManagers( - name='category', + name="category", managers=[ - ('tree', django.db.models.manager.Manager()), + ("tree", django.db.models.manager.Manager()), ], ), migrations.AlterField( - model_name='categoryrelation', - name='relation_type', - field=models.CharField(blank=True, help_text="A generic text field to tag a relation, like 'leadphoto'.", max_length=200, null=True, verbose_name='relation type'), + model_name="categoryrelation", + name="relation_type", + field=models.CharField( + blank=True, + help_text="A generic text field to tag a relation, like 'leadphoto'.", + max_length=200, + null=True, + verbose_name="relation type", + ), ), ] diff --git a/categories/migrations/0003_auto_20200306_1050.py b/categories/migrations/0003_auto_20200306_1050.py index c725321..21d98a3 100644 --- a/categories/migrations/0003_auto_20200306_1050.py +++ b/categories/migrations/0003_auto_20200306_1050.py @@ -1,35 +1,44 @@ # Generated by Django 3.0.4 on 2020-03-06 10:50 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), - ('categories', '0002_auto_20170217_1111'), + ("contenttypes", "0002_remove_content_type_name"), + ("categories", "0002_auto_20170217_1111"), ] operations = [ migrations.AlterField( - model_name='category', - name='level', + model_name="category", + name="level", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='category', - name='lft', + model_name="category", + name="lft", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='category', - name='rght', + model_name="category", + name="rght", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='categoryrelation', - name='content_type', - field=models.ForeignKey(limit_choices_to=models.Q(models.Q(('app_label', 'simpletext'), ('model', 'simpletext')), models.Q(('app_label', 'flatpages'), ('model', 'flatpage')), _connector='OR'), on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type'), + model_name="categoryrelation", + name="content_type", + field=models.ForeignKey( + limit_choices_to=models.Q( + models.Q(("app_label", "simpletext"), ("model", "simpletext")), + models.Q(("app_label", "flatpages"), ("model", "flatpage")), + _connector="OR", + ), + on_delete=django.db.models.deletion.CASCADE, + to="contenttypes.ContentType", + verbose_name="content type", + ), ), ] diff --git a/categories/migrations/0004_auto_20200517_1832.py b/categories/migrations/0004_auto_20200517_1832.py index ec3f2a0..dcbde23 100644 --- a/categories/migrations/0004_auto_20200517_1832.py +++ b/categories/migrations/0004_auto_20200517_1832.py @@ -1,20 +1,22 @@ # Generated by Django 3.0.6 on 2020-05-17 18:32 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), - ('categories', '0003_auto_20200306_1050'), + ("contenttypes", "0002_remove_content_type_name"), + ("categories", "0003_auto_20200306_1050"), ] operations = [ migrations.AlterField( - model_name='categoryrelation', - name='content_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='content type'), + model_name="categoryrelation", + name="content_type", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="contenttypes.ContentType", verbose_name="content type" + ), ), ] diff --git a/categories/models.py b/categories/models.py index 15ddecb..3789de6 100644 --- a/categories/models.py +++ b/categories/models.py @@ -1,20 +1,26 @@ -from django.core.files.images import get_image_dimensions -from django.urls import reverse -from django.db import models -from django.utils.encoding import force_text -from django.contrib.contenttypes.models import ContentType from functools import reduce + +from django.contrib.contenttypes.models import ContentType +from django.core.files.images import get_image_dimensions +from django.db import models +from django.urls import reverse +from django.utils.encoding import force_text + try: from django.contrib.contenttypes.fields import GenericForeignKey except ImportError: from django.contrib.contenttypes.generic import GenericForeignKey -from django.core.files.storage import get_storage_class +from django.core.files.storage import get_storage_class from django.utils.translation import ugettext_lazy as _ -from .settings import (RELATION_MODELS, RELATIONS, THUMBNAIL_UPLOAD_PATH, THUMBNAIL_STORAGE) - from .base import CategoryBase +from .settings import ( + RELATION_MODELS, + RELATIONS, + THUMBNAIL_STORAGE, + THUMBNAIL_UPLOAD_PATH, +) STORAGE = get_storage_class(THUMBNAIL_STORAGE) @@ -22,32 +28,28 @@ STORAGE = get_storage_class(THUMBNAIL_STORAGE) class Category(CategoryBase): thumbnail = models.FileField( upload_to=THUMBNAIL_UPLOAD_PATH, - null=True, blank=True, - storage=STORAGE(),) + null=True, + blank=True, + storage=STORAGE(), + ) thumbnail_width = models.IntegerField(blank=True, null=True) thumbnail_height = models.IntegerField(blank=True, null=True) order = models.IntegerField(default=0) alternate_title = models.CharField( - blank=True, - default="", - max_length=100, - help_text="An alternative title to use on pages with this category.") + blank=True, default="", max_length=100, help_text="An alternative title to use on pages with this category." + ) alternate_url = models.CharField( blank=True, max_length=200, - help_text="An alternative URL to use instead of the one derived from " - "the category hierarchy.") + help_text="An alternative URL to use instead of the one derived from " "the category hierarchy.", + ) description = models.TextField(blank=True, null=True) meta_keywords = models.CharField( - blank=True, - default="", - max_length=255, - help_text="Comma-separated keywords for search engines.") + blank=True, default="", max_length=255, help_text="Comma-separated keywords for search engines." + ) meta_extra = models.TextField( - blank=True, - default="", - help_text="(Advanced) Any additional HTML to be placed verbatim " - "in the <head>") + blank=True, default="", help_text="(Advanced) Any additional HTML to be placed verbatim " "in the <head>" + ) @property def short_title(self): @@ -60,19 +62,21 @@ class Category(CategoryBase): if self.alternate_url: return self.alternate_url try: - prefix = reverse('categories_tree_list') + prefix = reverse("categories_tree_list") except NoReverseMatch: - prefix = '/' - ancestors = list(self.get_ancestors()) + [self, ] - return prefix + '/'.join([force_text(i.slug) for i in ancestors]) + '/' + prefix = "/" + ancestors = list(self.get_ancestors()) + [ + self, + ] + return prefix + "/".join([force_text(i.slug) for i in ancestors]) + "/" if RELATION_MODELS: + def get_related_content_type(self, content_type): """ Get all related items of the specified content type """ - return self.categoryrelation_set.filter( - content_type__name=content_type) + return self.categoryrelation_set.filter(content_type__name=content_type) def get_relation_type(self, relation_type): """ @@ -92,11 +96,11 @@ class Category(CategoryBase): super(Category, self).save(*args, **kwargs) class Meta(CategoryBase.Meta): - verbose_name = _('category') - verbose_name_plural = _('categories') + verbose_name = _("category") + verbose_name_plural = _("categories") class MPTTMeta: - order_insertion_by = ('order', 'name') + order_insertion_by = ("order", "name") if RELATIONS: @@ -123,17 +127,23 @@ class CategoryRelationManager(models.Manager): class CategoryRelation(models.Model): """Related category item""" - category = models.ForeignKey(Category, verbose_name=_('category'), on_delete=models.CASCADE) + + category = models.ForeignKey(Category, verbose_name=_("category"), on_delete=models.CASCADE) content_type = models.ForeignKey( - ContentType, on_delete=models.CASCADE, limit_choices_to=CATEGORY_RELATION_LIMITS, verbose_name=_('content type')) - object_id = models.PositiveIntegerField(verbose_name=_('object id')) - content_object = GenericForeignKey('content_type', 'object_id') + ContentType, + on_delete=models.CASCADE, + limit_choices_to=CATEGORY_RELATION_LIMITS, + verbose_name=_("content type"), + ) + object_id = models.PositiveIntegerField(verbose_name=_("object id")) + content_object = GenericForeignKey("content_type", "object_id") relation_type = models.CharField( - verbose_name=_('relation type'), + verbose_name=_("relation type"), max_length=200, blank=True, null=True, - help_text=_("A generic text field to tag a relation, like 'leadphoto'.")) + help_text=_("A generic text field to tag a relation, like 'leadphoto'."), + ) objects = CategoryRelationManager() diff --git a/categories/registration.py b/categories/registration.py index e26bb12..d871e14 100644 --- a/categories/registration.py +++ b/categories/registration.py @@ -1,17 +1,17 @@ """ These functions handle the adding of fields to other models """ -from django.db.models import ForeignKey, ManyToManyField, CASCADE -from django.core.exceptions import FieldDoesNotExist -from . import fields +from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.db.models import CASCADE, ForeignKey, ManyToManyField + # from settings import self._field_registry, self._model_registry from django.utils.translation import ugettext_lazy as _ -from django.core.exceptions import ImproperlyConfigured +from . import fields FIELD_TYPES = { - 'ForeignKey': ForeignKey, - 'ManyToManyField': ManyToManyField, + "ForeignKey": ForeignKey, + "ManyToManyField": ManyToManyField, } @@ -28,17 +28,20 @@ class Registry(object): field_definitions: a string, tuple or list of field configurations field_type: either 'ForeignKey' or 'ManyToManyField' """ - from django.apps import apps import collections + from django.apps import apps + app_label = app if isinstance(field_definitions, str): field_definitions = [field_definitions] elif not isinstance(field_definitions, collections.Iterable): - raise ImproperlyConfigured(_('Field configuration for %(app)s should be a string or iterable') % {'app': app}) + raise ImproperlyConfigured( + _("Field configuration for %(app)s should be a string or iterable") % {"app": app} + ) - if field_type not in ('ForeignKey', 'ManyToManyField'): + if field_type not in ("ForeignKey", "ManyToManyField"): raise ImproperlyConfigured(_('`field_type` must be either `"ForeignKey"` or `"ManyToManyField"`.')) try: @@ -55,30 +58,31 @@ class Registry(object): if model not in self._model_registry[app_label]: self._model_registry[app_label].append(model) except LookupError: - raise ImproperlyConfigured('Model "%(model)s" doesn\'t exist in app "%(app)s".' % {'model': model_name, 'app': app}) + raise ImproperlyConfigured( + 'Model "%(model)s" doesn\'t exist in app "%(app)s".' % {"model": model_name, "app": app} + ) if not isinstance(field_definitions, (tuple, list)): field_definitions = [field_definitions] for fld in field_definitions: - extra_params = {'to': 'categories.Category', 'blank': True} - if field_type != 'ManyToManyField': - extra_params['on_delete'] = CASCADE - extra_params['null'] = True + extra_params = {"to": "categories.Category", "blank": True} + if field_type != "ManyToManyField": + extra_params["on_delete"] = CASCADE + extra_params["null"] = True if isinstance(fld, str): field_name = fld elif isinstance(fld, dict): - if 'name' in fld: - field_name = fld.pop('name') + if "name" in fld: + field_name = fld.pop("name") else: continue extra_params.update(fld) else: raise ImproperlyConfigured( - _("%(settings)s doesn't recognize the value of %(app)s.%(model)s") % { - 'settings': 'CATEGORY_SETTINGS', - 'app': app, - 'model': model_name}) + _("%(settings)s doesn't recognize the value of %(app)s.%(model)s") + % {"settings": "CATEGORY_SETTINGS", "app": app, "model": model_name} + ) registry_name = ".".join([app_label, model_name.lower(), field_name]) if registry_name in self._field_registry: continue @@ -89,10 +93,10 @@ class Registry(object): self._field_registry[registry_name] = FIELD_TYPES[field_type](**extra_params) self._field_registry[registry_name].contribute_to_class(model, field_name) - def register_m2m(self, model, field_name='categories', extra_params={}): + def register_m2m(self, model, field_name="categories", extra_params={}): return self._register(model, field_name, extra_params, fields.CategoryM2MField) - def register_fk(self, model, field_name='category', extra_params={}): + def register_fk(self, model, field_name="category", extra_params={}): return self._register(model, field_name, extra_params, fields.CategoryFKField) def _register(self, model, field_name, extra_params={}, field=fields.CategoryFKField): @@ -120,28 +124,32 @@ def _process_registry(registry, call_func): """ Given a dictionary, and a registration function, process the registry """ - from django.core.exceptions import ImproperlyConfigured from django.apps import apps + from django.core.exceptions import ImproperlyConfigured for key, value in list(registry.items()): - model = apps.get_model(*key.split('.')) + model = apps.get_model(*key.split(".")) if model is None: - raise ImproperlyConfigured(_('%(key)s is not a model') % {'key': key}) + raise ImproperlyConfigured(_("%(key)s is not a model") % {"key": key}) if isinstance(value, (tuple, list)): for item in value: if isinstance(item, str): call_func(model, item) elif isinstance(item, dict): - field_name = item.pop('name') + field_name = item.pop("name") call_func(model, field_name, extra_params=item) else: - raise ImproperlyConfigured(_("%(settings)s doesn't recognize the value of %(key)s") % - {'settings': 'CATEGORY_SETTINGS', 'key': key}) + raise ImproperlyConfigured( + _("%(settings)s doesn't recognize the value of %(key)s") + % {"settings": "CATEGORY_SETTINGS", "key": key} + ) elif isinstance(value, str): call_func(model, value) elif isinstance(value, dict): - field_name = value.pop('name') + field_name = value.pop("name") call_func(model, field_name, extra_params=value) else: - raise ImproperlyConfigured(_("%(settings)s doesn't recognize the value of %(key)s") % - {'settings': 'CATEGORY_SETTINGS', 'key': key}) + raise ImproperlyConfigured( + _("%(settings)s doesn't recognize the value of %(key)s") + % {"settings": "CATEGORY_SETTINGS", "key": key} + ) diff --git a/categories/settings.py b/categories/settings.py index bf77d66..2fedf6f 100644 --- a/categories/settings.py +++ b/categories/settings.py @@ -1,42 +1,46 @@ +import collections + from django.conf import settings from django.db.models import Q from django.utils.translation import ugettext_lazy as _ -import collections DEFAULT_SETTINGS = { - 'ALLOW_SLUG_CHANGE': False, - 'M2M_REGISTRY': {}, - 'FK_REGISTRY': {}, - 'THUMBNAIL_UPLOAD_PATH': 'uploads/categories/thumbnails', - 'THUMBNAIL_STORAGE': settings.DEFAULT_FILE_STORAGE, - 'JAVASCRIPT_URL': getattr(settings, 'STATIC_URL', settings.MEDIA_URL) + 'js/', - 'SLUG_TRANSLITERATOR': '', - 'REGISTER_ADMIN': True, - 'RELATION_MODELS': [], + "ALLOW_SLUG_CHANGE": False, + "M2M_REGISTRY": {}, + "FK_REGISTRY": {}, + "THUMBNAIL_UPLOAD_PATH": "uploads/categories/thumbnails", + "THUMBNAIL_STORAGE": settings.DEFAULT_FILE_STORAGE, + "JAVASCRIPT_URL": getattr(settings, "STATIC_URL", settings.MEDIA_URL) + "js/", + "SLUG_TRANSLITERATOR": "", + "REGISTER_ADMIN": True, + "RELATION_MODELS": [], } -DEFAULT_SETTINGS.update(getattr(settings, 'CATEGORIES_SETTINGS', {})) +DEFAULT_SETTINGS.update(getattr(settings, "CATEGORIES_SETTINGS", {})) -if DEFAULT_SETTINGS['SLUG_TRANSLITERATOR']: - if isinstance(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'], collections.Callable): +if DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"]: + if isinstance(DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"], collections.Callable): pass - elif isinstance(DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'], str): + elif isinstance(DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"], str): from django.utils.importlib import import_module - bits = DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'].split(".") + + bits = DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"].split(".") module = import_module(".".join(bits[:-1])) - DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'] = getattr(module, bits[-1]) + DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"] = getattr(module, bits[-1]) else: from django.core.exceptions import ImproperlyConfigured - raise ImproperlyConfigured(_('%(transliterator) must be a callable or a string.') % - {'transliterator': 'SLUG_TRANSLITERATOR'}) + + raise ImproperlyConfigured( + _("%(transliterator) must be a callable or a string.") % {"transliterator": "SLUG_TRANSLITERATOR"} + ) else: - DEFAULT_SETTINGS['SLUG_TRANSLITERATOR'] = lambda x: x + DEFAULT_SETTINGS["SLUG_TRANSLITERATOR"] = lambda x: x # Add all the keys/values to the module's namespace globals().update(DEFAULT_SETTINGS) -RELATIONS = [Q(app_label=al, model=m) for al, m in [x.split('.') for x in DEFAULT_SETTINGS['RELATION_MODELS']]] +RELATIONS = [Q(app_label=al, model=m) for al, m in [x.split(".") for x in DEFAULT_SETTINGS["RELATION_MODELS"]]] # The field registry keeps track of the individual fields created. # {'app.model.field': Field(**extra_params)} diff --git a/categories/static/js/genericcollections.js b/categories/static/js/genericcollections.js index 584208e..8081eb8 100644 --- a/categories/static/js/genericcollections.js +++ b/categories/static/js/genericcollections.js @@ -17,4 +17,4 @@ function showGenericRelatedObjectLookupPopup(triggeringLink, ctArray) { var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); win.focus(); return false; -} \ No newline at end of file +} diff --git a/categories/templates/categories/ancestors_ul.html b/categories/templates/categories/ancestors_ul.html index eb07cb2..d9173e2 100644 --- a/categories/templates/categories/ancestors_ul.html +++ b/categories/templates/categories/ancestors_ul.html @@ -8,4 +8,4 @@ {% else %}{{ node.name }} {% endifequal %} {% for level in structure.closed_levels %}{% endfor %} -{% endfor %} \ No newline at end of file +{% endfor %} diff --git a/categories/templates/categories/base.html b/categories/templates/categories/base.html index 385820f..245102a 100644 --- a/categories/templates/categories/base.html +++ b/categories/templates/categories/base.html @@ -1,3 +1,3 @@ {% extends 'base.html' %} {% block content %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/templates/categories/breadcrumbs.html b/categories/templates/categories/breadcrumbs.html index d6ec117..9fac9e2 100644 --- a/categories/templates/categories/breadcrumbs.html +++ b/categories/templates/categories/breadcrumbs.html @@ -1,3 +1,3 @@ {% spaceless %}{% for item in category.get_ancestors %} {{ item.name }}{{ separator }}{% endfor %}{{ category.name }} -{% endspaceless %} \ No newline at end of file +{% endspaceless %} diff --git a/categories/templates/categories/category_detail.html b/categories/templates/categories/category_detail.html index 3865fa1..c43e371 100644 --- a/categories/templates/categories/category_detail.html +++ b/categories/templates/categories/category_detail.html @@ -14,4 +14,4 @@ {% if category.parent %}

Go up to {{ category.parent }}

{% endif %} {% if category.description %}

{{ category.description }}

{% endif %} {% if category.children.count %}

Subcategories

{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/templates/categories/category_list.html b/categories/templates/categories/category_list.html index ff87511..f9a2c26 100644 --- a/categories/templates/categories/category_list.html +++ b/categories/templates/categories/category_list.html @@ -2,4 +2,4 @@ {% block content %}

Categories

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/categories/templates/categories/ul_tree.html b/categories/templates/categories/ul_tree.html index b6013de..891e298 100644 --- a/categories/templates/categories/ul_tree.html +++ b/categories/templates/categories/ul_tree.html @@ -8,4 +8,4 @@ {% else %}{{ node.name }} {% endifequal %} {% for level in structure.closed_levels %}{% endfor %} -{% endfor %}{% endspaceless %} \ No newline at end of file +{% endfor %}{% endspaceless %} diff --git a/categories/templatetags/category_tags.py b/categories/templatetags/category_tags.py index 69d2aad..a93f70e 100644 --- a/categories/templatetags/category_tags.py +++ b/categories/templatetags/category_tags.py @@ -1,13 +1,18 @@ from django import template from django.apps import apps -from django.template import (Node, TemplateSyntaxError, VariableDoesNotExist) +from django.template import Node, TemplateSyntaxError, VariableDoesNotExist from django.template.base import FilterExpression +from mptt.templatetags.mptt_tags import ( + RecurseTreeNode, + full_tree_for_model, + tree_info, + tree_path, +) +from mptt.utils import drilldown_tree_for_node from six import string_types + from categories.base import CategoryBase from categories.models import Category -from mptt.utils import drilldown_tree_for_node -from mptt.templatetags.mptt_tags import (tree_path, tree_info, RecurseTreeNode, - full_tree_for_model) register = template.Library() @@ -48,9 +53,9 @@ def get_category(category_string, model=Category): """ model_class = get_cat_model(model) category = str(category_string).strip("'\"") - category = category.strip('/') + category = category.strip("/") - cat_list = category.split('/') + cat_list = category.split("/") if len(cat_list) == 0: return None try: @@ -88,7 +93,7 @@ class CategoryDrillDownNode(template.Node): context[self.varname] = [] except Exception: context[self.varname] = [] - return '' + return "" @register.tag @@ -114,30 +119,32 @@ def get_category_drilldown(parser, token): Grandparent, Parent, Child 1, Child 2, Child n """ bits = token.split_contents() - error_str = '%(tagname)s tag should be in the format {%% %(tagname)s ' \ - '"category name" [using "app.Model"] as varname %%} or ' \ - '{%% %(tagname)s category_obj as varname %%}.' + error_str = ( + "%(tagname)s tag should be in the format {%% %(tagname)s " + '"category name" [using "app.Model"] as varname %%} or ' + "{%% %(tagname)s category_obj as varname %%}." + ) if len(bits) == 4: - if bits[2] != 'as': - raise template.TemplateSyntaxError(error_str % {'tagname': bits[0]}) - if bits[2] == 'as': + if bits[2] != "as": + raise template.TemplateSyntaxError(error_str % {"tagname": bits[0]}) + if bits[2] == "as": varname = bits[3].strip("'\"") model = "categories.category" if len(bits) == 6: - if bits[2] not in ('using', 'as') or bits[4] not in ('using', 'as'): - raise template.TemplateSyntaxError(error_str % {'tagname': bits[0]}) - if bits[2] == 'as': + if bits[2] not in ("using", "as") or bits[4] not in ("using", "as"): + raise template.TemplateSyntaxError(error_str % {"tagname": bits[0]}) + if bits[2] == "as": varname = bits[3].strip("'\"") model = bits[5].strip("'\"") - if bits[2] == 'using': + if bits[2] == "using": varname = bits[5].strip("'\"") model = bits[3].strip("'\"") category = FilterExpression(bits[1], parser) return CategoryDrillDownNode(category, varname, model) -@register.inclusion_tag('categories/breadcrumbs.html') -def breadcrumbs(category_string, separator=' > ', using='categories.category'): +@register.inclusion_tag("categories/breadcrumbs.html") +def breadcrumbs(category_string, separator=" > ", using="categories.category"): """ {% breadcrumbs category separator="::" using="categories.category" %} @@ -146,11 +153,11 @@ def breadcrumbs(category_string, separator=' > ', using='categories.category'): """ cat = get_category(category_string, using) - return {'category': cat, 'separator': separator} + return {"category": cat, "separator": separator} -@register.inclusion_tag('categories/ul_tree.html') -def display_drilldown_as_ul(category, using='categories.Category'): +@register.inclusion_tag("categories/ul_tree.html") +def display_drilldown_as_ul(category, using="categories.Category"): """ Render the category with ancestors and children using the ``categories/ul_tree.html`` template. @@ -185,13 +192,13 @@ def display_drilldown_as_ul(category, using='categories.Category'): """ cat = get_category(category, using) if cat is None: - return {'category': cat, 'path': []} + return {"category": cat, "path": []} else: - return {'category': cat, 'path': drilldown_tree_for_node(cat)} + return {"category": cat, "path": drilldown_tree_for_node(cat)} -@register.inclusion_tag('categories/ul_tree.html') -def display_path_as_ul(category, using='categories.Category'): +@register.inclusion_tag("categories/ul_tree.html") +def display_path_as_ul(category, using="categories.Category"): """ Render the category with ancestors, but no children using the ``categories/ul_tree.html`` template. @@ -219,7 +226,7 @@ def display_path_as_ul(category, using='categories.Category'): else: cat = get_category(category) - return {'category': cat, 'path': cat.get_ancestors() or []} + return {"category": cat, "path": cat.get_ancestors() or []} class TopLevelCategoriesNode(template.Node): @@ -229,8 +236,8 @@ class TopLevelCategoriesNode(template.Node): def render(self, context): model = get_cat_model(self.model) - context[self.varname] = model.objects.filter(parent=None).order_by('name') - return '' + context[self.varname] = model.objects.filter(parent=None).order_by("name") + return "" @register.tag @@ -247,14 +254,14 @@ def get_top_level_categories(parser, token): bits = token.split_contents() usage = 'Usage: {%% %s [using "app.Model"] as %%}' % bits[0] if len(bits) == 3: - if bits[1] != 'as': + if bits[1] != "as": raise template.TemplateSyntaxError(usage) varname = bits[2] model = "categories.category" elif len(bits) == 5: - if bits[1] not in ('as', 'using') and bits[3] not in ('as', 'using'): + if bits[1] not in ("as", "using") and bits[3] not in ("as", "using"): raise template.TemplateSyntaxError(usage) - if bits[1] == 'using': + if bits[1] == "using": model = bits[2].strip("'\"") varname = bits[4].strip("'\"") else: @@ -264,22 +271,21 @@ def get_top_level_categories(parser, token): return TopLevelCategoriesNode(varname, model) -def get_latest_objects_by_category(category, app_label, model_name, set_name, date_field='pub_date', num=15): +def get_latest_objects_by_category(category, app_label, model_name, set_name, date_field="pub_date", num=15): m = apps.get_model(app_label, model_name) if not isinstance(category, CategoryBase): category = Category.objects.get(slug=str(category)) children = category.children.all() ids = [] for cat in list(children) + [category]: - if hasattr(cat, '%s_set' % set_name): - ids.extend([x.pk for x in getattr(cat, '%s_set' % set_name).all()[:num]]) + if hasattr(cat, "%s_set" % set_name): + ids.extend([x.pk for x in getattr(cat, "%s_set" % set_name).all()[:num]]) - return m.objects.filter(pk__in=ids).order_by('-%s' % date_field)[:num] + return m.objects.filter(pk__in=ids).order_by("-%s" % date_field)[:num] class LatestObjectsNode(Node): - def __init__(self, var_name, category, app_label, model_name, set_name, - date_field='pub_date', num=15): + def __init__(self, var_name, category, app_label, model_name, set_name, date_field="pub_date", num=15): """ Get latest objects of app_label.model_name """ @@ -305,7 +311,7 @@ class LatestObjectsNode(Node): result = get_latest_objects_by_category(category, app_label, model_name, set_name, date_field, num) context[self.var_name] = result - return '' + return "" def do_get_latest_objects_by_category(parser, token): @@ -317,7 +323,7 @@ def do_get_latest_objects_by_category(parser, token): proper_form = "{% get_latest_objects_by_category category app_name model_name set_name [date_field] [number] as [var_name] %}" bits = token.split_contents() - if bits[-2] != 'as': + if bits[-2] != "as": raise TemplateSyntaxError("%s tag shoud be in the form: %s" % (bits[0], proper_form)) if len(bits) < 7: raise TemplateSyntaxError("%s tag shoud be in the form: %s" % (bits[0], proper_form)) @@ -328,11 +334,11 @@ def do_get_latest_objects_by_category(parser, token): model_name = FilterExpression(bits[3], parser) set_name = FilterExpression(bits[4], parser) var_name = bits[-1] - if bits[5] != 'as': + if bits[5] != "as": date_field = FilterExpression(bits[5], parser) else: date_field = FilterExpression(None, parser) - if bits[6] != 'as': + if bits[6] != "as": num = FilterExpression(bits[6], parser) else: num = FilterExpression(None, parser) @@ -348,8 +354,10 @@ def tree_queryset(value): Converts a normal queryset from an MPTT model to include all the ancestors so a filtered subset of items can be formatted correctly """ - from django.db.models.query import QuerySet from copy import deepcopy + + from django.db.models.query import QuerySet + if not isinstance(value, QuerySet): return value @@ -365,9 +373,9 @@ def tree_queryset(value): # this cuts down the number of queries considerably since all ancestors # will already be in include_pages when they are checked, thus not # trigger additional queries. - for p in qs2.order_by('rght').iterator(): + for p in qs2.order_by("rght").iterator(): if p.parent_id and p.parent_id not in include_pages and p.id not in include_pages: - ancestor_id_list = p.get_ancestors().values_list('id', flat=True) + ancestor_id_list = p.get_ancestors().values_list("id", flat=True) include_pages.update(ancestor_id_list) if include_pages: @@ -400,10 +408,10 @@ def recursetree(parser, token): """ bits = token.contents.split() if len(bits) != 2: - raise template.TemplateSyntaxError('%s tag requires a queryset' % bits[0]) + raise template.TemplateSyntaxError("%s tag requires a queryset" % bits[0]) queryset_var = FilterExpression(bits[1], parser) - template_nodes = parser.parse(('endrecursetree',)) + template_nodes = parser.parse(("endrecursetree",)) parser.delete_first_token() return RecurseTreeNode(template_nodes, queryset_var) diff --git a/categories/tests/test_admin.py b/categories/tests/test_admin.py index 20759c1..ce1c7a3 100644 --- a/categories/tests/test_admin.py +++ b/categories/tests/test_admin.py @@ -1,68 +1,68 @@ -# -*- coding: utf-8 -*- from django.contrib.auth.models import User -from django.urls import reverse from django.test import Client, TestCase +from django.urls import reverse from django.utils.encoding import smart_text from categories.models import Category class TestCategoryAdmin(TestCase): - def setUp(self): self.client = Client() def test_adding_parent_and_child(self): - User.objects.create_superuser('testuser', 'testuser@example.com', 'password') - self.client.login(username='testuser', password='password') - url = reverse('admin:categories_category_add') + User.objects.create_superuser("testuser", "testuser@example.com", "password") + self.client.login(username="testuser", password="password") + url = reverse("admin:categories_category_add") data = { - 'parent': '', - 'name': smart_text('Parent Catégory'), - 'thumbnail': '', - 'filename': '', - 'active': 'on', - 'alternate_title': '', - 'alternate_url': '', - 'description': '', - 'meta_keywords': '', - 'meta_extra': '', - 'order': 0, - 'slug': 'parent', - '_save': '_save', - 'categoryrelation_set-TOTAL_FORMS': '0', - 'categoryrelation_set-INITIAL_FORMS': '0', - 'categoryrelation_set-MIN_NUM_FORMS': '1000', - 'categoryrelation_set-MAX_NUM_FORMS': '1000', + "parent": "", + "name": smart_text("Parent Catégory"), + "thumbnail": "", + "filename": "", + "active": "on", + "alternate_title": "", + "alternate_url": "", + "description": "", + "meta_keywords": "", + "meta_extra": "", + "order": 0, + "slug": "parent", + "_save": "_save", + "categoryrelation_set-TOTAL_FORMS": "0", + "categoryrelation_set-INITIAL_FORMS": "0", + "categoryrelation_set-MIN_NUM_FORMS": "1000", + "categoryrelation_set-MAX_NUM_FORMS": "1000", } resp = self.client.post(url, data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(1, Category.objects.count()) # update parent - data.update({'name': smart_text('Parent Catégory (Changed)')}) - resp = self.client.post(reverse('admin:categories_category_change', args=(1,)), data=data) + data.update({"name": smart_text("Parent Catégory (Changed)")}) + resp = self.client.post(reverse("admin:categories_category_change", args=(1,)), data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(1, Category.objects.count()) # add a child - data.update({ - 'parent': '1', - 'name': smart_text('Child Catégory'), - 'slug': smart_text('child-category'), - }) + data.update( + { + "parent": "1", + "name": smart_text("Child Catégory"), + "slug": smart_text("child-category"), + } + ) resp = self.client.post(url, data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(2, Category.objects.count()) # update child - data.update({'name': 'Child (Changed)'}) - resp = self.client.post(reverse('admin:categories_category_change', args=(2,)), data=data) + data.update({"name": "Child (Changed)"}) + resp = self.client.post(reverse("admin:categories_category_change", args=(2,)), data=data) self.assertEqual(resp.status_code, 302) self.assertEqual(2, Category.objects.count()) # test the admin list view - url = reverse('admin:categories_category_changelist') + url = reverse("admin:categories_category_changelist") resp = self.client.get(url) self.assertEqual(resp.status_code, 200) diff --git a/categories/tests/test_category_import.py b/categories/tests/test_category_import.py index 3db1be4..acd366f 100644 --- a/categories/tests/test_category_import.py +++ b/categories/tests/test_category_import.py @@ -4,20 +4,21 @@ import os from django.conf import settings -from django.test import TestCase, override_settings -from categories.models import Category -from categories.management.commands.import_categories import Command from django.core.management.base import CommandError +from django.test import TestCase, override_settings + +from categories.management.commands.import_categories import Command +from categories.models import Category -@override_settings(INSTALLED_APPS=(app for app in settings.INSTALLED_APPS if app != 'django.contrib.flatpages')) +@override_settings(INSTALLED_APPS=(app for app in settings.INSTALLED_APPS if app != "django.contrib.flatpages")) class CategoryImportTest(TestCase): def setUp(self): pass def _import_file(self, filename): - root_cats = ['Category 1', 'Category 2', 'Category 3'] - testfile = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures', filename)) + root_cats = ["Category 1", "Category 2", "Category 3"] + testfile = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), "fixtures", filename)) cmd = Command() cmd.handle(testfile) roots = Category.tree.root_nodes() @@ -26,31 +27,31 @@ class CategoryImportTest(TestCase): for item in roots: assert item.name in root_cats - cat2 = Category.objects.get(name='Category 2') + cat2 = Category.objects.get(name="Category 2") cat21 = cat2.children.all()[0] - self.assertEqual(cat21.name, 'Category 2-1') + self.assertEqual(cat21.name, "Category 2-1") cat211 = cat21.children.all()[0] - self.assertEqual(cat211.name, 'Category 2-1-1') + self.assertEqual(cat211.name, "Category 2-1-1") def testImportSpaceDelimited(self): Category.objects.all().delete() - self._import_file('test_category_spaces.txt') + self._import_file("test_category_spaces.txt") items = Category.objects.all() - self.assertEqual(items[0].name, 'Category 1') - self.assertEqual(items[1].name, 'Category 1-1') - self.assertEqual(items[2].name, 'Category 1-2') + self.assertEqual(items[0].name, "Category 1") + self.assertEqual(items[1].name, "Category 1-1") + self.assertEqual(items[2].name, "Category 1-2") def testImportTabDelimited(self): Category.objects.all().delete() - self._import_file('test_category_tabs.txt') + self._import_file("test_category_tabs.txt") items = Category.objects.all() - self.assertEqual(items[0].name, 'Category 1') - self.assertEqual(items[1].name, 'Category 1-1') - self.assertEqual(items[2].name, 'Category 1-2') + self.assertEqual(items[0].name, "Category 1") + self.assertEqual(items[1].name, "Category 1-1") + self.assertEqual(items[2].name, "Category 1-2") def testMixingTabsSpaces(self): """ diff --git a/categories/tests/test_manager.py b/categories/tests/test_manager.py index b2fb6c6..a9f2718 100644 --- a/categories/tests/test_manager.py +++ b/categories/tests/test_manager.py @@ -1,10 +1,11 @@ # test active returns only active items from django.test import TestCase + from categories.models import Category class CategoryManagerTest(TestCase): - fixtures = ['categories.json'] + fixtures = ["categories.json"] def setUp(self): pass @@ -16,7 +17,7 @@ class CategoryManagerTest(TestCase): all_count = Category.objects.all().count() self.assertEqual(Category.objects.active().count(), all_count) - cat1 = Category.objects.get(name='Category 1') + cat1 = Category.objects.get(name="Category 1") cat1.active = False cat1.save() diff --git a/categories/tests/test_mgmt_commands.py b/categories/tests/test_mgmt_commands.py index 7466910..b94c842 100644 --- a/categories/tests/test_mgmt_commands.py +++ b/categories/tests/test_mgmt_commands.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core import management from django.core.management.base import CommandError from django.db import connection @@ -6,7 +5,6 @@ from django.test import TestCase class TestMgmtCommands(TestCase): - @classmethod def setUpClass(cls): connection.disable_constraint_checking() @@ -18,13 +16,13 @@ class TestMgmtCommands(TestCase): connection.enable_constraint_checking() def test_add_category_fields(self): - management.call_command('add_category_fields', verbosity=0) + management.call_command("add_category_fields", verbosity=0) def test_add_category_fields_app(self): - management.call_command('add_category_fields', 'flatpages', verbosity=0) + management.call_command("add_category_fields", "flatpages", verbosity=0) def test_drop_category_field(self): - management.call_command('drop_category_field', 'flatpages', 'flatpage', 'category', verbosity=0) + management.call_command("drop_category_field", "flatpages", "flatpage", "category", verbosity=0) def test_drop_category_field_error(self): - self.assertRaises(CommandError, management.call_command, 'drop_category_field', verbosity=0) + self.assertRaises(CommandError, management.call_command, "drop_category_field", verbosity=0) diff --git a/categories/tests/test_models.py b/categories/tests/test_models.py index 5649bee..5208baf 100644 --- a/categories/tests/test_models.py +++ b/categories/tests/test_models.py @@ -2,20 +2,19 @@ import os from django.core.files import File from django.core.files.uploadedfile import UploadedFile +from django.test import TestCase from categories.models import Category -from django.test import TestCase class TestCategoryThumbnail(TestCase): - def test_thumbnail(self): - file_name = 'test_image.jpg' + file_name = "test_image.jpg" - with open(os.path.join(os.path.dirname(__file__), file_name), 'rb') as f: - test_image = UploadedFile(File(f), content_type='image/jpeg') - category = Category.objects.create(name='Test Category', slug='test-category', thumbnail=test_image) + with open(os.path.join(os.path.dirname(__file__), file_name), "rb") as f: + test_image = UploadedFile(File(f), content_type="image/jpeg") + category = Category.objects.create(name="Test Category", slug="test-category", thumbnail=test_image) self.assertEqual(category.pk, 1) self.assertEqual(category.thumbnail_width, 640) self.assertEqual(category.thumbnail_height, 480) diff --git a/categories/tests/test_registration.py b/categories/tests/test_registration.py index 842baec..918d8c9 100644 --- a/categories/tests/test_registration.py +++ b/categories/tests/test_registration.py @@ -14,43 +14,39 @@ class CategoryRegistrationTest(TestCase): """ def test_foreignkey_string(self): - FK_REGISTRY = { - 'flatpages.flatpage': 'category' - } + FK_REGISTRY = {"flatpages.flatpage": "category"} _process_registry(FK_REGISTRY, registry.register_fk) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) def test_foreignkey_dict(self): - FK_REGISTRY = { - 'flatpages.flatpage': {'name': 'category'} - } + FK_REGISTRY = {"flatpages.flatpage": {"name": "category"}} _process_registry(FK_REGISTRY, registry.register_fk) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) def test_foreignkey_list(self): - FK_REGISTRY = { - 'flatpages.flatpage': ( - {'name': 'category', 'related_name': 'cats'}, - ) - } + FK_REGISTRY = {"flatpages.flatpage": ({"name": "category", "related_name": "cats"},)} _process_registry(FK_REGISTRY, registry.register_fk) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) if django.VERSION[1] >= 7: + def test_new_foreignkey_string(self): - registry.register_model('flatpages', 'flatpage', 'ForeignKey', 'category') + registry.register_model("flatpages", "flatpage", "ForeignKey", "category") from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) class Categorym2mTest(TestCase): def test_m2m_string(self): - M2M_REGISTRY = { - 'flatpages.flatpage': 'categories' - } + M2M_REGISTRY = {"flatpages.flatpage": "categories"} _process_registry(M2M_REGISTRY, registry.register_m2m) from django.contrib.flatpages.models import FlatPage - self.assertTrue('category' in [f.name for f in FlatPage()._meta.get_fields()]) + + self.assertTrue("category" in [f.name for f in FlatPage()._meta.get_fields()]) diff --git a/categories/tests/test_templatetags.py b/categories/tests/test_templatetags.py index f099715..ffe967c 100644 --- a/categories/tests/test_templatetags.py +++ b/categories/tests/test_templatetags.py @@ -1,13 +1,14 @@ -from django.test import TestCase -from django import template import re +from django import template +from django.test import TestCase + from categories.models import Category class CategoryTagsTest(TestCase): - fixtures = ['musicgenres.json'] + fixtures = ["musicgenres.json"] def render_template(self, template_string, context={}): """ @@ -21,7 +22,9 @@ class CategoryTagsTest(TestCase): """ Ensure that get_category raises an exception if there aren't enough arguments. """ - self.assertRaises(template.TemplateSyntaxError, self.render_template, '{% load category_tags %}{% get_category %}') + self.assertRaises( + template.TemplateSyntaxError, self.render_template, "{% load category_tags %}{% get_category %}" + ) def testBasicUsage(self): """ @@ -30,46 +33,50 @@ class CategoryTagsTest(TestCase): # display_path_as_ul rock_resp = '' resp = self.render_template('{% load category_tags %}{% display_path_as_ul "/Rock" %}') - resp = re.sub(r'\n$', "", resp) + resp = re.sub(r"\n$", "", resp) self.assertEqual(resp, rock_resp) # display_drilldown_as_ul expected_resp = '' resp = self.render_template( - '{% load category_tags %}' - '{% display_drilldown_as_ul "/World/Worldbeat" "categories.category" %}') - resp = re.sub(r'\n$', "", resp) + "{% load category_tags %}" '{% display_drilldown_as_ul "/World/Worldbeat" "categories.category" %}' + ) + resp = re.sub(r"\n$", "", resp) self.assertEqual(resp, expected_resp) # breadcrumbs expected_resp = 'World > Worldbeat' resp = self.render_template( - '{% load category_tags %}' - '{% breadcrumbs "/World/Worldbeat" " > " "categories.category" %}') + "{% load category_tags %}" '{% breadcrumbs "/World/Worldbeat" " > " "categories.category" %}' + ) self.assertEqual(resp, expected_resp) # get_top_level_categories - expected_resp = 'Avant-garde|Blues|Country|Easy listening|Electronic|Hip hop/Rap music|Jazz|Latin|Modern folk|Pop|Reggae|Rhythm and blues|Rock|World|' + expected_resp = "Avant-garde|Blues|Country|Easy listening|Electronic|Hip hop/Rap music|Jazz|Latin|Modern folk|Pop|Reggae|Rhythm and blues|Rock|World|" resp = self.render_template( - '{% load category_tags %}' + "{% load category_tags %}" '{% get_top_level_categories using "categories.category" as varname %}' - '{% for item in varname %}{{ item }}|{% endfor %}') + "{% for item in varname %}{{ item }}|{% endfor %}" + ) self.assertEqual(resp, expected_resp) # get_category_drilldown expected_resp = "World|World > Worldbeat|" resp = self.render_template( - '{% load category_tags %}' + "{% load category_tags %}" '{% get_category_drilldown "/World" using "categories.category" as var %}' - '{% for item in var %}{{ item }}|{% endfor %}') + "{% for item in var %}{{ item }}|{% endfor %}" + ) self.assertEqual(resp, expected_resp) # recursetree - expected_resp = '
  • Country
    • Country pop
      • Urban Cowboy
  • World
    • Worldbeat
    ' - ctxt = {'nodes': Category.objects.filter(name__in=("Worldbeat", "Urban Cowboy"))} + expected_resp = "
    • Country
      • Country pop
        • Urban Cowboy
    • World
      • Worldbeat
      " + ctxt = {"nodes": Category.objects.filter(name__in=("Worldbeat", "Urban Cowboy"))} resp = self.render_template( - '{% load category_tags %}' - '
        {% recursetree nodes|tree_queryset %}
      • {{ node.name }}' - '{% if not node.is_leaf_node %}
          {{ children }}' - '
        {% endif %}
      • {% endrecursetree %}
      ', ctxt) + "{% load category_tags %}" + "
        {% recursetree nodes|tree_queryset %}
      • {{ node.name }}" + "{% if not node.is_leaf_node %}
          {{ children }}" + "
        {% endif %}
      • {% endrecursetree %}
      ", + ctxt, + ) self.assertEqual(resp, expected_resp) diff --git a/categories/tests/test_views.py b/categories/tests/test_views.py index d64435b..dac65f9 100644 --- a/categories/tests/test_views.py +++ b/categories/tests/test_views.py @@ -1,8 +1,9 @@ -from django.http import Http404 from django.contrib.auth.models import AnonymousUser -from django.test import Client, TestCase, RequestFactory -from categories.models import Category, CategoryRelation +from django.http import Http404 +from django.test import Client, RequestFactory, TestCase + from categories import views +from categories.models import Category, CategoryRelation class MyCategoryRelationView(views.CategoryRelatedDetail): @@ -10,16 +11,18 @@ class MyCategoryRelationView(views.CategoryRelatedDetail): class TestCategoryViews(TestCase): - fixtures = ['musicgenres.json', ] + fixtures = [ + "musicgenres.json", + ] def setUp(self): self.client = Client() self.factory = RequestFactory() def test_category_detail(self): - cat0 = Category.objects.get(slug='country', level=0) - cat1 = cat0.children.get(slug='country-pop') - cat2 = Category.objects.get(slug='urban-cowboy') + cat0 = Category.objects.get(slug="country", level=0) + cat1 = cat0.children.get(slug="country-pop") + cat2 = Category.objects.get(slug="urban-cowboy") url = cat0.get_absolute_url() response = self.client.get(url) self.assertEquals(response.status_code, 200) @@ -33,51 +36,48 @@ class TestCategoryViews(TestCase): self.assertEquals(response.status_code, 404) def test_get_category_for_path(self): - cat0 = Category.objects.get(slug='country', level=0) - cat1 = cat0.children.get(slug='country-pop') - cat2 = Category.objects.get(slug='urban-cowboy') + cat0 = Category.objects.get(slug="country", level=0) + cat1 = cat0.children.get(slug="country-pop") + cat2 = Category.objects.get(slug="urban-cowboy") - result = views.get_category_for_path('/country/country-pop/urban-cowboy/') + result = views.get_category_for_path("/country/country-pop/urban-cowboy/") self.assertEquals(result, cat2) - result = views.get_category_for_path('/country/country-pop/') + result = views.get_category_for_path("/country/country-pop/") self.assertEquals(result, cat1) - result = views.get_category_for_path('/country/') + result = views.get_category_for_path("/country/") self.assertEquals(result, cat0) def test_categorydetailview(self): - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() self.assertRaises(AttributeError, views.CategoryDetailView.as_view(), request) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - response = views.CategoryDetailView.as_view()(request, path='/country/country-pop/urban-cowboy/') + response = views.CategoryDetailView.as_view()(request, path="/country/country-pop/urban-cowboy/") self.assertEquals(response.status_code, 200) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - self.assertRaises(Http404, views.CategoryDetailView.as_view(), request, path='/country/country-pop/foo/') + self.assertRaises(Http404, views.CategoryDetailView.as_view(), request, path="/country/country-pop/foo/") def test_categoryrelateddetailview(self): from simpletext.models import SimpleText - stext = SimpleText.objects.create( - name='Test', - description='test description' - ) - cat = Category.objects.get(slug='urban-cowboy') - cat_rel = CategoryRelation.objects.create( # NOQA - category=cat, - content_object=stext - ) - request = self.factory.get('') + + stext = SimpleText.objects.create(name="Test", description="test description") + cat = Category.objects.get(slug="urban-cowboy") + cat_rel = CategoryRelation.objects.create(category=cat, content_object=stext) # NOQA + request = self.factory.get("") request.user = AnonymousUser() self.assertRaises(AttributeError, MyCategoryRelationView.as_view(), request) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - response = MyCategoryRelationView.as_view()(request, category_path='/country/country-pop/urban-cowboy/') + response = MyCategoryRelationView.as_view()(request, category_path="/country/country-pop/urban-cowboy/") self.assertEquals(response.status_code, 200) - request = self.factory.get('') + request = self.factory.get("") request.user = AnonymousUser() - self.assertRaises(Http404, MyCategoryRelationView.as_view(), request, category_path='/country/country-pop/foo/') + self.assertRaises( + Http404, MyCategoryRelationView.as_view(), request, category_path="/country/country-pop/foo/" + ) diff --git a/categories/urls.py b/categories/urls.py index 986df79..7160f61 100644 --- a/categories/urls.py +++ b/categories/urls.py @@ -1,19 +1,11 @@ from django.conf.urls import url from django.views.generic import ListView -from .models import Category + from . import views +from .models import Category +categorytree_dict = {"queryset": Category.objects.filter(level=0)} -categorytree_dict = { - 'queryset': Category.objects.filter(level=0) -} +urlpatterns = (url(r"^$", ListView.as_view(**categorytree_dict), name="categories_tree_list"),) -urlpatterns = ( - url( - r'^$', ListView.as_view(**categorytree_dict), name='categories_tree_list' - ), -) - -urlpatterns += ( - url(r'^(?P.+)/$', views.category_detail, name='categories_category'), -) +urlpatterns += (url(r"^(?P.+)/$", views.category_detail, name="categories_category"),) diff --git a/categories/views.py b/categories/views.py index 65584f6..c92752d 100644 --- a/categories/views.py +++ b/categories/views.py @@ -1,5 +1,5 @@ +from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404 -from django.http import HttpResponse, Http404 from django.template.loader import select_template from django.utils.translation import ugettext_lazy as _ from django.views.generic import DetailView, ListView @@ -7,139 +7,126 @@ from django.views.generic import DetailView, ListView from .models import Category -def category_detail(request, path, template_name='categories/category_detail.html', extra_context={}): - path_items = path.strip('/').split('/') +def category_detail(request, path, template_name="categories/category_detail.html", extra_context={}): + path_items = path.strip("/").split("/") if len(path_items) >= 2: category = get_object_or_404( - Category, - slug__iexact=path_items[-1], - level=len(path_items) - 1, - parent__slug__iexact=path_items[-2]) + Category, slug__iexact=path_items[-1], level=len(path_items) - 1, parent__slug__iexact=path_items[-2] + ) else: - category = get_object_or_404( - Category, - slug__iexact=path_items[-1], - level=len(path_items) - 1) + category = get_object_or_404(Category, slug__iexact=path_items[-1], level=len(path_items) - 1) templates = [] while path_items: - templates.append('categories/%s.html' % '_'.join(path_items)) + templates.append("categories/%s.html" % "_".join(path_items)) path_items.pop() templates.append(template_name) - context = {'category': category} + context = {"category": category} if extra_context: context.update(extra_context) return HttpResponse(select_template(templates).render(context)) def get_category_for_path(path, queryset=Category.objects.all()): - path_items = path.strip('/').split('/') + path_items = path.strip("/").split("/") if len(path_items) >= 2: queryset = queryset.filter( - slug__iexact=path_items[-1], - level=len(path_items) - 1, - parent__slug__iexact=path_items[-2]) + slug__iexact=path_items[-1], level=len(path_items) - 1, parent__slug__iexact=path_items[-2] + ) else: - queryset = queryset.filter( - slug__iexact=path_items[-1], - level=len(path_items) - 1) + queryset = queryset.filter(slug__iexact=path_items[-1], level=len(path_items) - 1) return queryset.get() class CategoryDetailView(DetailView): model = Category - path_field = 'path' + path_field = "path" def get_object(self, **kwargs): if self.path_field not in self.kwargs: - raise AttributeError("Category detail view %s must be called with " - "a %s." % (self.__class__.__name__, self.path_field)) + raise AttributeError( + "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) + ) if self.queryset is None: queryset = self.get_queryset() try: return get_category_for_path(self.kwargs[self.path_field], self.model.objects.all()) except Category.DoesNotExist: - raise Http404(_("No %(verbose_name)s found matching the query") % - {'verbose_name': queryset.model._meta.verbose_name}) + raise Http404( + _("No %(verbose_name)s found matching the query") % {"verbose_name": queryset.model._meta.verbose_name} + ) def get_template_names(self): names = [] - path_items = self.kwargs[self.path_field].strip('/').split('/') + path_items = self.kwargs[self.path_field].strip("/").split("/") while path_items: - names.append('categories/%s.html' % '_'.join(path_items)) + names.append("categories/%s.html" % "_".join(path_items)) path_items.pop() names.extend(super(CategoryDetailView, self).get_template_names()) return names class CategoryRelatedDetail(DetailView): - path_field = 'category_path' + path_field = "category_path" object_name_field = None def get_object(self, **kwargs): if self.path_field not in self.kwargs: - raise AttributeError("Category detail view %s must be called with " - "a %s." % (self.__class__.__name__, self.path_field)) + raise AttributeError( + "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) + ) queryset = super(CategoryRelatedDetail, self).get_queryset() try: category = get_category_for_path(self.kwargs[self.path_field]) except Category.DoesNotExist: - raise Http404(_("No %(verbose_name)s found matching the query") % - {'verbose_name': queryset.model._meta.verbose_name}) + raise Http404( + _("No %(verbose_name)s found matching the query") % {"verbose_name": queryset.model._meta.verbose_name} + ) return queryset.get(category=category) def get_template_names(self): names = [] opts = self.object._meta - path_items = self.kwargs[self.path_field].strip('/').split('/') + path_items = self.kwargs[self.path_field].strip("/").split("/") if self.object_name_field: path_items.append(getattr(self.object, self.object_name_field)) while path_items: - names.append('%s/category_%s_%s%s.html' % ( - opts.app_label, - '_'.join(path_items), - opts.object_name.lower(), - self.template_name_suffix) + names.append( + "%s/category_%s_%s%s.html" + % (opts.app_label, "_".join(path_items), opts.object_name.lower(), self.template_name_suffix) ) path_items.pop() - names.append('%s/category_%s%s.html' % ( - opts.app_label, - opts.object_name.lower(), - self.template_name_suffix) - ) + names.append("%s/category_%s%s.html" % (opts.app_label, opts.object_name.lower(), self.template_name_suffix)) names.extend(super(CategoryRelatedDetail, self).get_template_names()) return names class CategoryRelatedList(ListView): - path_field = 'category_path' + path_field = "category_path" def get_queryset(self): if self.path_field not in self.kwargs: - raise AttributeError("Category detail view %s must be called with " - "a %s." % (self.__class__.__name__, self.path_field)) + raise AttributeError( + "Category detail view %s must be called with " "a %s." % (self.__class__.__name__, self.path_field) + ) queryset = super(CategoryRelatedList, self).get_queryset() category = get_category_for_path(self.kwargs[self.path_field]) return queryset.filter(category=category) def get_template_names(self): names = [] - if hasattr(self.object_list, 'model'): + if hasattr(self.object_list, "model"): opts = self.object_list.model._meta - path_items = self.kwargs[self.path_field].strip('/').split('/') + path_items = self.kwargs[self.path_field].strip("/").split("/") while path_items: - names.append('%s/category_%s_%s%s.html' % ( - opts.app_label, - '_'.join(path_items), - opts.object_name.lower(), - self.template_name_suffix) + names.append( + "%s/category_%s_%s%s.html" + % (opts.app_label, "_".join(path_items), opts.object_name.lower(), self.template_name_suffix) ) path_items.pop() - names.append('%s/category_%s%s.html' % ( - opts.app_label, - opts.object_name.lower(), - self.template_name_suffix) + names.append( + "%s/category_%s%s.html" % (opts.app_label, opts.object_name.lower(), self.template_name_suffix) ) names.extend(super(CategoryRelatedList, self).get_template_names()) return names diff --git a/doc_src/_static/default.css b/doc_src/_static/default.css index c719235..a95ff54 100644 --- a/doc_src/_static/default.css +++ b/doc_src/_static/default.css @@ -770,4 +770,4 @@ display:inline; } li p { margin-top:8px; -} \ No newline at end of file +} diff --git a/doc_src/_static/toc.js b/doc_src/_static/toc.js index 7b70978..cc06ee8 100644 --- a/doc_src/_static/toc.js +++ b/doc_src/_static/toc.js @@ -17,4 +17,4 @@ var TOC = { $(document).ready(function () { TOC.load(); -}); \ No newline at end of file +}); diff --git a/doc_src/adding_the_fields.rst b/doc_src/adding_the_fields.rst index a6a920f..b40709b 100644 --- a/doc_src/adding_the_fields.rst +++ b/doc_src/adding_the_fields.rst @@ -20,4 +20,4 @@ Reconfiguring Fields You can make changes to the field configurations as long as they do not change the underlying database structure. For example, adding a ``related_name`` (see :ref:`registering_a_m2one_relationship`\ ) because it only affects Django code. Changing the name of the field, however, is a different matter. -Django Categories provides a complementary management command to drop a field from the database (the field must still be in the configuration to do so): ``python manage.py drop_category_field app_name model_name field_name`` \ No newline at end of file +Django Categories provides a complementary management command to drop a field from the database (the field must still be in the configuration to do so): ``python manage.py drop_category_field app_name model_name field_name`` diff --git a/doc_src/code_examples/custom_categories1.py b/doc_src/code_examples/custom_categories1.py index c8d4652..68a437e 100644 --- a/doc_src/code_examples/custom_categories1.py +++ b/doc_src/code_examples/custom_categories1.py @@ -7,4 +7,4 @@ class SimpleCategory(CategoryBase): """ class Meta: - verbose_name_plural = 'simple categories' + verbose_name_plural = "simple categories" diff --git a/doc_src/code_examples/custom_categories3.py b/doc_src/code_examples/custom_categories3.py index d2aaa6f..27babd9 100644 --- a/doc_src/code_examples/custom_categories3.py +++ b/doc_src/code_examples/custom_categories3.py @@ -5,29 +5,25 @@ from categories.base import CategoryBase class Category(CategoryBase): thumbnail = models.FileField( upload_to=settings.THUMBNAIL_UPLOAD_PATH, - null=True, blank=True, - storage=settings.THUMBNAIL_STORAGE,) + null=True, + blank=True, + storage=settings.THUMBNAIL_STORAGE, + ) thumbnail_width = models.IntegerField(blank=True, null=True) thumbnail_height = models.IntegerField(blank=True, null=True) order = models.IntegerField(default=0) alternate_title = models.CharField( - blank=True, - default="", - max_length=100, - help_text="An alternative title to use on pages with this category.") + blank=True, default="", max_length=100, help_text="An alternative title to use on pages with this category." + ) alternate_url = models.CharField( blank=True, max_length=200, - help_text="An alternative URL to use instead of the one derived from " - "the category hierarchy.") + help_text="An alternative URL to use instead of the one derived from " "the category hierarchy.", + ) description = models.TextField(blank=True, null=True) meta_keywords = models.CharField( - blank=True, - default="", - max_length=255, - help_text="Comma-separated keywords for search engines.") + blank=True, default="", max_length=255, help_text="Comma-separated keywords for search engines." + ) meta_extra = models.TextField( - blank=True, - default="", - help_text="(Advanced) Any additional HTML to be placed verbatim " - "in the <head>") + blank=True, default="", help_text="(Advanced) Any additional HTML to be placed verbatim " "in the <head>" + ) diff --git a/doc_src/code_examples/custom_categories4.py b/doc_src/code_examples/custom_categories4.py index 87e1d3a..9356e05 100644 --- a/doc_src/code_examples/custom_categories4.py +++ b/doc_src/code_examples/custom_categories4.py @@ -3,8 +3,9 @@ from categories.models import Category def save(self, *args, **kwargs): if self.thumbnail: - from django.core.files.images import get_image_dimensions import django + from django.core.files.images import get_image_dimensions + if django.VERSION[1] < 2: width, height = get_image_dimensions(self.thumbnail.file) else: diff --git a/doc_src/code_examples/custom_categories5.py b/doc_src/code_examples/custom_categories5.py index 67109c6..e2f48d4 100644 --- a/doc_src/code_examples/custom_categories5.py +++ b/doc_src/code_examples/custom_categories5.py @@ -2,8 +2,8 @@ from categories.base import CategoryBase class Meta(CategoryBase.Meta): - verbose_name_plural = 'categories' + verbose_name_plural = "categories" class MPTTMeta: - order_insertion_by = ('order', 'name') + order_insertion_by = ("order", "name") diff --git a/doc_src/code_examples/custom_categories6.py b/doc_src/code_examples/custom_categories6.py index 3c09f03..387aa72 100644 --- a/doc_src/code_examples/custom_categories6.py +++ b/doc_src/code_examples/custom_categories6.py @@ -7,7 +7,7 @@ class CategoryAdminForm(CategoryBaseAdminForm): model = Category def clean_alternate_title(self): - if self.instance is None or not self.cleaned_data['alternate_title']: - return self.cleaned_data['name'] + if self.instance is None or not self.cleaned_data["alternate_title"]: + return self.cleaned_data["name"] else: - return self.cleaned_data['alternate_title'] + return self.cleaned_data["alternate_title"] diff --git a/doc_src/code_examples/custom_categories7.py b/doc_src/code_examples/custom_categories7.py index 4fcc1a2..6ec7041 100644 --- a/doc_src/code_examples/custom_categories7.py +++ b/doc_src/code_examples/custom_categories7.py @@ -4,18 +4,21 @@ from categories.base import CategoryBaseAdmin class CategoryAdmin(CategoryBaseAdmin): form = CategoryAdminForm - list_display = ('name', 'alternate_title', 'active') + list_display = ("name", "alternate_title", "active") fieldsets = ( - (None, { - 'fields': ('parent', 'name', 'thumbnail', 'active') - }), - ('Meta Data', { - 'fields': ('alternate_title', 'alternate_url', 'description', - 'meta_keywords', 'meta_extra'), - 'classes': ('collapse',), - }), - ('Advanced', { - 'fields': ('order', 'slug'), - 'classes': ('collapse',), - }), + (None, {"fields": ("parent", "name", "thumbnail", "active")}), + ( + "Meta Data", + { + "fields": ("alternate_title", "alternate_url", "description", "meta_keywords", "meta_extra"), + "classes": ("collapse",), + }, + ), + ( + "Advanced", + { + "fields": ("order", "slug"), + "classes": ("collapse",), + }, + ), ) diff --git a/doc_src/conf.py b/doc_src/conf.py index 0ffb72f..f8400c6 100644 --- a/doc_src/conf.py +++ b/doc_src/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Django Categories documentation build configuration file, created by # sphinx-quickstart on Tue Oct 6 07:53:33 2009. @@ -11,14 +10,14 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os +import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath('..')) -os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings' +sys.path.append(os.path.abspath("..")) +os.environ["DJANGO_SETTINGS_MODULE"] = "example.settings" import categories # noqa @@ -32,17 +31,17 @@ extensions = [] templates_path = ['_templates'] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. # ource_encoding = 'utf-8' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'Django Categories' -copyright = '2010-2012, Corey Oordt' +project = "Django Categories" +copyright = "2010-2012, Corey Oordt" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -68,7 +67,7 @@ release = categories.get_version() # List of directories, relative to source directory, that shouldn't be searched # for source files. -exclude_trees = ['_build'] +exclude_trees = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. # efault_role = None @@ -85,7 +84,7 @@ exclude_trees = ['_build'] # how_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # odindex_common_prefix = [] @@ -124,7 +123,7 @@ html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -162,7 +161,7 @@ html_static_path = ['_static'] # tml_file_suffix = '' # Output file base name for HTML help builder. -htmlhelp_basename = 'DjangoCategoriesdoc' +htmlhelp_basename = "DjangoCategoriesdoc" # -- Options for LaTeX output -------------------------------------------------- @@ -176,7 +175,7 @@ htmlhelp_basename = 'DjangoCategoriesdoc' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'DjangoCategories.tex', 'Django Categories Documentation', 'CoreyOordt', 'manual'), + ("index", "DjangoCategories.tex", "Django Categories Documentation", "CoreyOordt", "manual"), ] # The name of an image file (relative to this directory) to place at the top of diff --git a/doc_src/index.rst b/doc_src/index.rst index 9c330ed..093de5a 100644 --- a/doc_src/index.rst +++ b/doc_src/index.rst @@ -41,4 +41,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - diff --git a/doc_src/reference/management_commands.rst b/doc_src/reference/management_commands.rst index b090695..4818672 100644 --- a/doc_src/reference/management_commands.rst +++ b/doc_src/reference/management_commands.rst @@ -35,4 +35,4 @@ drop_category_field Drop the ``field_name`` field from the ``app_name_model_name`` table, if the field is currently registered in ``CATEGORIES_SETTINGS``\ . -Requires Django South. \ No newline at end of file +Requires Django South. diff --git a/doc_src/reference/settings.rst b/doc_src/reference/settings.rst index dd0ebee..96c542f 100644 --- a/doc_src/reference/settings.rst +++ b/doc_src/reference/settings.rst @@ -128,4 +128,4 @@ ADMIN_FIELDSETS **Default:** ``{}`` -**Description:** Allows for selective customization of the default behavior of adding the fields to the admin class. See :ref:`admin_settings` for more information. \ No newline at end of file +**Description:** Allows for selective customization of the default behavior of adding the fields to the admin class. See :ref:`admin_settings` for more information. diff --git a/doc_src/usage.rst b/doc_src/usage.rst index c54c3b2..83e9779 100644 --- a/doc_src/usage.rst +++ b/doc_src/usage.rst @@ -59,4 +59,3 @@ comma-separated list of feature names. The valid feature names are: Books -> [] Sci-fi -> [u'Books'] Dystopian Futures -> [u'Books', u'Sci-fi'] - diff --git a/doc_src/usage_example_template.html b/doc_src/usage_example_template.html index b0bee73..9428cf6 100644 --- a/doc_src/usage_example_template.html +++ b/doc_src/usage_example_template.html @@ -25,4 +25,4 @@

      No entries for {{ category }}

      {% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/example/settings-testing.py b/example/settings-testing.py index 9d2c3f1..ba91a32 100644 --- a/example/settings-testing.py +++ b/example/settings-testing.py @@ -16,108 +16,105 @@ ADMINS = ( MANAGERS = ADMINS DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'dev.db', - 'USER': '', - 'PASSWORD': '', - 'HOST': '', - 'PORT': '', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "dev.db", + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", } } INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.flatpages', - 'categories', - 'categories.editor', - 'mptt', - 'simpletext', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.flatpages", + "categories", + "categories.editor", + "mptt", + "simpletext", ) -TIME_ZONE = 'America/Chicago' +TIME_ZONE = "America/Chicago" -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" SITE_ID = 1 USE_I18N = True -MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'uploads')) +MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "uploads")) -MEDIA_URL = '/uploads/' +MEDIA_URL = "/uploads/" -STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'static')) +STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "static")) -STATIC_URL = '/static/' +STATIC_URL = "/static/" STATICFILES_DIRS = () STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", ) -SECRET_KEY = 'bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d' +SECRET_KEY = "bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d" MIDDLEWARE = ( - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ) -ROOT_URLCONF = 'urls' +ROOT_URLCONF = "urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'DIRS': [os.path.abspath(os.path.join(os.path.dirname(__file__), 'templates'))], - 'OPTIONS': { - 'debug': DEBUG, - 'context_processors': [ - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "DIRS": [os.path.abspath(os.path.join(os.path.dirname(__file__), "templates"))], + "OPTIONS": { + "debug": DEBUG, + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", ], - } + }, }, ] CATEGORIES_SETTINGS = { - 'ALLOW_SLUG_CHANGE': True, - 'RELATION_MODELS': ['simpletext.simpletext', 'flatpages.flatpage'], - 'FK_REGISTRY': { - 'flatpages.flatpage': ( - 'category', - {'on_delete': models.CASCADE} - ), - 'simpletext.simpletext': ( - 'primary_category', - {'name': 'secondary_category', 'related_name': 'simpletext_sec_cat'}, + "ALLOW_SLUG_CHANGE": True, + "RELATION_MODELS": ["simpletext.simpletext", "flatpages.flatpage"], + "FK_REGISTRY": { + "flatpages.flatpage": ("category", {"on_delete": models.CASCADE}), + "simpletext.simpletext": ( + "primary_category", + {"name": "secondary_category", "related_name": "simpletext_sec_cat"}, ), }, - 'M2M_REGISTRY': { + "M2M_REGISTRY": { # 'simpletext.simpletext': {'name': 'categories', 'related_name': 'm2mcats'}, - 'flatpages.flatpage': ( - {'name': 'other_categories', 'related_name': 'other_cats'}, - {'name': 'more_categories', 'related_name': 'more_cats'}, + "flatpages.flatpage": ( + {"name": "other_categories", "related_name": "other_cats"}, + {"name": "more_categories", "related_name": "more_cats"}, ), }, } -TEST_RUNNER = 'django.test.runner.DiscoverRunner' +TEST_RUNNER = "django.test.runner.DiscoverRunner" diff --git a/example/settings.py b/example/settings.py index 6eab74a..c303377 100644 --- a/example/settings.py +++ b/example/settings.py @@ -1,6 +1,7 @@ # Django settings for sample project. import os import sys + import django from django.db import models @@ -16,109 +17,106 @@ ADMINS = ( MANAGERS = ADMINS DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'dev.db', - 'USER': '', - 'PASSWORD': '', - 'HOST': '', - 'PORT': '', + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "dev.db", + "USER": "", + "PASSWORD": "", + "HOST": "", + "PORT": "", } } INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.flatpages', - 'categories', - 'categories.editor', - 'mptt', - 'simpletext', + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.flatpages", + "categories", + "categories.editor", + "mptt", + "simpletext", ) -TIME_ZONE = 'America/Chicago' +TIME_ZONE = "America/Chicago" -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" SITE_ID = 1 USE_I18N = True -MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'uploads')) +MEDIA_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "uploads")) -MEDIA_URL = '/uploads/' +MEDIA_URL = "/uploads/" -STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, 'media', 'static')) +STATIC_ROOT = os.path.abspath(os.path.join(PROJ_ROOT, "media", "static")) -STATIC_URL = '/static/' +STATIC_URL = "/static/" STATICFILES_DIRS = () STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", ) -SECRET_KEY = 'bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d' +SECRET_KEY = "bwq#m)-zsey-fs)0#4*o=2z(v5g!ei=zytl9t-1hesh4b&-u^d" MIDDLEWARE = ( - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ) -ROOT_URLCONF = 'urls' +ROOT_URLCONF = "urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'APP_DIRS': True, - 'DIRS': [os.path.abspath(os.path.join(os.path.dirname(__file__), 'templates'))], - 'OPTIONS': { - 'debug': DEBUG, - 'context_processors': [ - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "DIRS": [os.path.abspath(os.path.join(os.path.dirname(__file__), "templates"))], + "OPTIONS": { + "debug": DEBUG, + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.contrib.messages.context_processors.messages", ], - } + }, } ] CATEGORIES_SETTINGS = { - 'ALLOW_SLUG_CHANGE': True, - 'RELATION_MODELS': ['simpletext.simpletext', 'flatpages.flatpage'], - 'FK_REGISTRY': { - 'flatpages.flatpage': ( - 'category', - {'on_delete': models.CASCADE} - ), - 'simpletext.simpletext': ( - 'primary_category', - {'name': 'secondary_category', 'related_name': 'simpletext_sec_cat'}, + "ALLOW_SLUG_CHANGE": True, + "RELATION_MODELS": ["simpletext.simpletext", "flatpages.flatpage"], + "FK_REGISTRY": { + "flatpages.flatpage": ("category", {"on_delete": models.CASCADE}), + "simpletext.simpletext": ( + "primary_category", + {"name": "secondary_category", "related_name": "simpletext_sec_cat"}, ), }, - 'M2M_REGISTRY': { - 'simpletext.simpletext': {'name': 'categories', 'related_name': 'm2mcats'}, - 'flatpages.flatpage': ( - {'name': 'other_categories', 'related_name': 'other_cats'}, - {'name': 'more_categories', 'related_name': 'more_cats'}, + "M2M_REGISTRY": { + "simpletext.simpletext": {"name": "categories", "related_name": "m2mcats"}, + "flatpages.flatpage": ( + {"name": "other_categories", "related_name": "other_cats"}, + {"name": "more_categories", "related_name": "more_cats"}, ), }, } if django.VERSION[1] > 5: - TEST_RUNNER = 'django.test.runner.DiscoverRunner' + TEST_RUNNER = "django.test.runner.DiscoverRunner" diff --git a/example/simpletext/admin.py b/example/simpletext/admin.py index dcf1947..9539514 100644 --- a/example/simpletext/admin.py +++ b/example/simpletext/admin.py @@ -1,21 +1,28 @@ -from .models import SimpleText, SimpleCategory from django.contrib import admin from categories.admin import CategoryBaseAdmin, CategoryBaseAdminForm +from .models import SimpleCategory, SimpleText + class SimpleTextAdmin(admin.ModelAdmin): fieldsets = ( - (None, { - 'fields': ('name', 'description', ) - }), + ( + None, + { + "fields": ( + "name", + "description", + ) + }, + ), ) class SimpleCategoryAdminForm(CategoryBaseAdminForm): class Meta: model = SimpleCategory - fields = '__all__' + fields = "__all__" class SimpleCategoryAdmin(CategoryBaseAdmin): diff --git a/example/simpletext/migrations/0001_initial.py b/example/simpletext/migrations/0001_initial.py index d66db39..fe231e1 100644 --- a/example/simpletext/migrations/0001_initial.py +++ b/example/simpletext/migrations/0001_initial.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.13 on 2017-10-12 20:27 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import mptt.fields +from django.db import migrations, models class Migration(migrations.Migration): @@ -15,35 +14,45 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='SimpleCategory', + name="SimpleCategory", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100, verbose_name='name')), - ('slug', models.SlugField(verbose_name='slug')), - ('active', models.BooleanField(default=True, verbose_name='active')), - ('lft', models.PositiveIntegerField(db_index=True, editable=False)), - ('rght', models.PositiveIntegerField(db_index=True, editable=False)), - ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), - ('level', models.PositiveIntegerField(db_index=True, editable=False)), - ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='simpletext.SimpleCategory', verbose_name='parent')), + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("name", models.CharField(max_length=100, verbose_name="name")), + ("slug", models.SlugField(verbose_name="slug")), + ("active", models.BooleanField(default=True, verbose_name="active")), + ("lft", models.PositiveIntegerField(db_index=True, editable=False)), + ("rght", models.PositiveIntegerField(db_index=True, editable=False)), + ("tree_id", models.PositiveIntegerField(db_index=True, editable=False)), + ("level", models.PositiveIntegerField(db_index=True, editable=False)), + ( + "parent", + mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="children", + to="simpletext.SimpleCategory", + verbose_name="parent", + ), + ), ], options={ - 'verbose_name_plural': 'simple categories', + "verbose_name_plural": "simple categories", }, ), migrations.CreateModel( - name='SimpleText', + name="SimpleText", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('description', models.TextField(blank=True)), - ('created', models.DateTimeField(auto_now_add=True)), - ('updated', models.DateTimeField(auto_now=True)), + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("name", models.CharField(max_length=255)), + ("description", models.TextField(blank=True)), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), ], options={ - 'ordering': ('-created',), - 'get_latest_by': 'updated', - 'verbose_name_plural': 'Simple Text', + "ordering": ("-created",), + "get_latest_by": "updated", + "verbose_name_plural": "Simple Text", }, ), ] diff --git a/example/simpletext/migrations/0002_auto_20171204_0721.py b/example/simpletext/migrations/0002_auto_20171204_0721.py index 2205f4c..6ce4e0a 100644 --- a/example/simpletext/migrations/0002_auto_20171204_0721.py +++ b/example/simpletext/migrations/0002_auto_20171204_0721.py @@ -1,39 +1,46 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-12-04 07:21 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import django.db.models.manager +from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('categories', '0002_auto_20170217_1111'), - ('simpletext', '0001_initial'), + ("categories", "0002_auto_20170217_1111"), + ("simpletext", "0001_initial"), ] operations = [ migrations.AlterModelManagers( - name='simplecategory', + name="simplecategory", managers=[ - ('tree', django.db.models.manager.Manager()), + ("tree", django.db.models.manager.Manager()), ], ), migrations.AddField( - model_name='simpletext', - name='categories', - field=models.ManyToManyField(blank=True, related_name='m2mcats', to='categories.Category'), + model_name="simpletext", + name="categories", + field=models.ManyToManyField(blank=True, related_name="m2mcats", to="categories.Category"), ), migrations.AddField( - model_name='simpletext', - name='primary_category', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='categories.Category'), + model_name="simpletext", + name="primary_category", + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to="categories.Category" + ), ), migrations.AddField( - model_name='simpletext', - name='secondary_category', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='simpletext_sec_cat', to='categories.Category'), + model_name="simpletext", + name="secondary_category", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="simpletext_sec_cat", + to="categories.Category", + ), ), ] diff --git a/example/simpletext/migrations/0003_auto_20200306_0928.py b/example/simpletext/migrations/0003_auto_20200306_0928.py index 0d786bc..a33be27 100644 --- a/example/simpletext/migrations/0003_auto_20200306_0928.py +++ b/example/simpletext/migrations/0003_auto_20200306_0928.py @@ -6,23 +6,23 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('simpletext', '0002_auto_20171204_0721'), + ("simpletext", "0002_auto_20171204_0721"), ] operations = [ migrations.AlterField( - model_name='simplecategory', - name='level', + model_name="simplecategory", + name="level", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='simplecategory', - name='lft', + model_name="simplecategory", + name="lft", field=models.PositiveIntegerField(editable=False), ), migrations.AlterField( - model_name='simplecategory', - name='rght', + model_name="simplecategory", + name="rght", field=models.PositiveIntegerField(editable=False), ), ] diff --git a/example/simpletext/models.py b/example/simpletext/models.py index 0fe96d1..e7ccaed 100755 --- a/example/simpletext/models.py +++ b/example/simpletext/models.py @@ -14,9 +14,9 @@ class SimpleText(models.Model): updated = models.DateTimeField(auto_now=True) class Meta: - verbose_name_plural = 'Simple Text' - ordering = ('-created',) - get_latest_by = 'updated' + verbose_name_plural = "Simple Text" + ordering = ("-created",) + get_latest_by = "updated" def __unicode__(self): return self.name @@ -24,16 +24,19 @@ class SimpleText(models.Model): def get_absolute_url(self): try: from django.db.models import permalink - return permalink('simpletext_detail_view_name', [str(self.id)]) + + return permalink("simpletext_detail_view_name", [str(self.id)]) except ImportError: from django.urls import reverse - return reverse('simpletext_detail_view_name', args=[str(self.id)]) + + return reverse("simpletext_detail_view_name", args=[str(self.id)]) class SimpleCategory(CategoryBase): """A Test of catgorizing""" + class Meta: - verbose_name_plural = 'simple categories' + verbose_name_plural = "simple categories" # mport categories diff --git a/example/simpletext/tests.py b/example/simpletext/tests.py index 73d6465..f51d798 100755 --- a/example/simpletext/tests.py +++ b/example/simpletext/tests.py @@ -16,9 +16,11 @@ class SimpleTest(TestCase): self.assertEqual(1 + 1, 2) -__test__ = {"doctest": """ +__test__ = { + "doctest": """ Another way to test that 1 + 1 is equal to 2. >>> 1 + 1 == 2 True -"""} +""" +} diff --git a/example/static/editor/jquery.treeTable.css b/example/static/editor/jquery.treeTable.css index f9fccd9..26828b6 100644 --- a/example/static/editor/jquery.treeTable.css +++ b/example/static/editor/jquery.treeTable.css @@ -62,4 +62,4 @@ .treeTable .ui-draggable-dragging { color: #000; z-index: 1; -} \ No newline at end of file +} diff --git a/example/static/editor/jquery.treeTable.js b/example/static/editor/jquery.treeTable.js index 522b2c5..412bdaf 100644 --- a/example/static/editor/jquery.treeTable.js +++ b/example/static/editor/jquery.treeTable.js @@ -455,4 +455,4 @@ function parentOf(node) { return $(node).parentOf(); } -})(django.jQuery); \ No newline at end of file +})(django.jQuery); diff --git a/example/static/js/genericcollections.js b/example/static/js/genericcollections.js index 584208e..8081eb8 100644 --- a/example/static/js/genericcollections.js +++ b/example/static/js/genericcollections.js @@ -17,4 +17,4 @@ function showGenericRelatedObjectLookupPopup(triggeringLink, ctArray) { var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); win.focus(); return false; -} \ No newline at end of file +} diff --git a/example/urls.py b/example/urls.py index 4c34998..cab9d28 100644 --- a/example/urls.py +++ b/example/urls.py @@ -12,23 +12,16 @@ ROOT_PATH = os.path.dirname(os.path.dirname(__file__)) urlpatterns = ( # Example: # (r'^sample/', include('sample.foo.urls')), - # Uncomment the admin/doc line below and add 'django.contrib.admindocs' # to INSTALLED_APPS to enable admin documentation: # (r'^admin/doc/', include('django.contrib.admindocs.urls')), - # Uncomment the next line to enable the admin: - url(r'^admin/', admin.site.urls), - url(r'^categories/', include('categories.urls')), + url(r"^admin/", admin.site.urls), + url(r"^categories/", include("categories.urls")), # r'^cats/', include('categories.urls')), - - url(r'^static/categories/(?P.*)$', serve, - {'document_root': ROOT_PATH + '/categories/media/categories/'}), - + url(r"^static/categories/(?P.*)$", serve, {"document_root": ROOT_PATH + "/categories/media/categories/"}), # (r'^static/editor/(?P.*)$', 'django.views.static.serve', # {'document_root': ROOT_PATH + '/editor/media/editor/', # 'show_indexes':True}), - - url(r'^static/(?P.*)$', serve, {'document_root': os.path.join(ROOT_PATH, 'example', 'static')}), - + url(r"^static/(?P.*)$", serve, {"document_root": os.path.join(ROOT_PATH, "example", "static")}), )