Unverified Kaydet (Commit) dbcf1c9d authored tarafından Uğur Özyılmazel's avatar Uğur Özyılmazel

New release - version: 1.3.0

    - Upgrade all python packages
    - Django 2.1.7
    - Fix SoftDelete related objects
üst 57340eea
[![Build Status](https://travis-ci.org/vigo/django2-project-template.svg?branch=master)](https://travis-ci.org/vigo/django2-project-template)
![Python](https://img.shields.io/badge/django-3.7.0-green.svg)
![Django](https://img.shields.io/badge/django-2.1.5-green.svg)
![Version](https://img.shields.io/badge/version-1.2.0-yellow.svg)
![Django](https://img.shields.io/badge/django-2.1.7-green.svg)
![Version](https://img.shields.io/badge/version-1.3.0-yellow.svg)
# Django Project Starter Template
......@@ -524,9 +524,10 @@ need to create a copy of it! (*if you follow along from the beginning, you’ve
All the base/common required Python packages/modules are defined under `requirements/base.pip`:
```python
django-extensions==2.1.3
Django==2.1.7
Pillow==5.4.1
django-extensions==2.1.4
django-extensions==2.1.6
python-slugify==3.0.0
```
### `base.py`
......@@ -645,14 +646,14 @@ All the required modules are defined under `requirements/development.pip`:
```python
-r base.pip
ipython==7.1.1
Werkzeug==0.14.1
ipython==7.3.0
Werkzeug==0.15.0
django-debug-toolbar==1.11
coverage==4.5.2
isort==4.3.4
black==18.9b0
flake8==3.6.0
flake8-bandit==2.0.0
coverage==4.5.3
isort==4.3.15
black==19.3b0
flake8==3.7.7
flake8-bandit==2.1.0
flake8-blind-except==0.1.1
flake8-bugbear==18.8.0
flake8-builtins==1.4.1
......@@ -660,7 +661,7 @@ flake8-polyfill==1.0.2
flake8-print==3.1.0
flake8-quotes==1.0.0
flake8-string-format==0.2.3
pylint==2.2.2
pylint==2.3.1
```
### `test.example.py`
......@@ -693,7 +694,7 @@ All the required modules are defined under `requirements/heroku.pip`:
```python
-r base.pip
gunicorn==19.9.0
psycopg2-binary==2.7.6.1
psycopg2-binary==2.7.7
dj-database-url==0.5.0
whitenoise==4.1.2
```
......
# isort:skip_file
# flake8: noqa
from .user import *
from .base import *
......@@ -20,25 +20,21 @@ class BaseAdmin(admin.ModelAdmin):
def get_list_filter(self, request):
list_filter = list(super().get_list_filter(request))
if self.sticky_list_filter:
list_filter = list(
self.sticky_list_filter
) + list(list_filter)
list_filter = list(self.sticky_list_filter) + list(list_filter)
return list_filter
def recover_selected(modeladmin, request, queryset):
number_of_rows_recovered, recovered_items = (
queryset.undelete()
)
number_of_rows_recovered, recovered_items = queryset.undelete()
if number_of_rows_recovered == 1:
message_bit = _('1 record was')
else:
message_bit = _(
'%(number_of_rows)s records were'
) % dict(number_of_rows=number_of_rows_recovered)
message = _(
'%(message_bit)s successfully marked as active'
) % dict(message_bit=message_bit)
message_bit = _('%(number_of_rows)s records were') % dict(
number_of_rows=number_of_rows_recovered
)
message = _('%(message_bit)s successfully marked as active') % dict(
message_bit=message_bit
)
modeladmin.message_user(request, message)
return None
......@@ -55,28 +51,20 @@ def hard_delete_selected(modeladmin, request, queryset):
raise PermissionDenied
n = queryset.count()
if n:
number_of_rows_deleted, deleted_items = (
queryset.hard_delete()
)
number_of_rows_deleted, deleted_items = queryset.hard_delete()
if number_of_rows_deleted == 1:
message_bit = _('1 record was')
else:
message_bit = _(
'%(number_of_rows)s records were'
) % dict(
message_bit = _('%(number_of_rows)s records were') % dict(
number_of_rows=number_of_rows_deleted
)
message = _('%(message_bit)s deleted') % dict(
message_bit=message_bit
)
message = _('%(message_bit)s deleted') % dict(message_bit=message_bit)
modeladmin.message_user(request, message)
return None
objects_name = model_ngettext(queryset)
if perms_needed or protected:
title = _('Cannot delete %(name)s') % {
'name': objects_name
}
title = _('Cannot delete %(name)s') % {'name': objects_name}
else:
title = _('Are you sure?')
......@@ -97,9 +85,7 @@ def hard_delete_selected(modeladmin, request, queryset):
request.current_app = modeladmin.admin_site.name
return TemplateResponse(
request,
'admin/hard_delete_selected_confirmation.html',
context,
request, 'admin/hard_delete_selected_confirmation.html', context
)
......@@ -110,10 +96,7 @@ class BaseAdminWithSoftDelete(BaseAdmin):
def get_queryset(self, request):
qs = self.model.objects.get_queryset()
if request.GET.get('status__exact', None):
if (
numerify(request.GET.get('status__exact'))
== BaseModel.STATUS_DELETED
):
if numerify(request.GET.get('status__exact')) == BaseModel.STATUS_DELETED:
return qs.deleted()
return qs.all()
......@@ -131,9 +114,7 @@ class BaseAdminWithSoftDelete(BaseAdmin):
recover_selected=(
recover_selected,
'recover_selected',
_(
'Recover selected %(verbose_name_plural)s'
),
_('Recover selected %(verbose_name_plural)s'),
)
)
)
......@@ -142,9 +123,7 @@ class BaseAdminWithSoftDelete(BaseAdmin):
hard_delete_selected=(
hard_delete_selected,
'hard_delete_selected',
_(
'Hard delete selected %(verbose_name_plural)s'
),
_('Hard delete selected %(verbose_name_plural)s'),
)
)
)
......
......@@ -18,19 +18,9 @@ class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = (
'user_profile_image',
'email',
'first_name',
'last_name',
)
list_display = ('user_profile_image', 'email', 'first_name', 'last_name')
list_display_links = ('email',)
search_fields = (
'email',
'first_name',
'middle_name',
'last_name',
)
search_fields = ('email', 'first_name', 'middle_name', 'last_name')
ordering = ('email',)
fieldsets = (
(
......@@ -74,9 +64,7 @@ class UserAdmin(BaseUserAdmin):
},
),
)
formfield_overrides = {
models.FileField: {'widget': AdminImageFileWidget}
}
formfield_overrides = {models.FileField: {'widget': AdminImageFileWidget}}
def user_profile_image(self, obj):
if obj.avatar:
......@@ -88,9 +76,7 @@ class UserAdmin(BaseUserAdmin):
else:
return '---'
user_profile_image.short_description = _(
'Profile Image'
)
user_profile_image.short_description = _('Profile Image')
admin.site.register(User, UserAdmin)
from .user import * # noqa
# isort:skip_file
# flake8: noqa
from .user import *
......@@ -43,12 +43,9 @@ class UserChangeForm(forms.ModelForm):
class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(
label=_('Password'), widget=forms.PasswordInput
)
password1 = forms.CharField(label=_('Password'), widget=forms.PasswordInput)
password2 = forms.CharField(
label=_('Password confirmation'),
widget=forms.PasswordInput,
label=_('Password confirmation'), widget=forms.PasswordInput
)
class Meta:
......@@ -66,20 +63,12 @@ class UserCreationForm(forms.ModelForm):
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if (
password1
and password2
and password1 != password2
):
raise forms.ValidationError(
_('Passwords don\'t match')
)
if password1 and password2 and password1 != password2:
raise forms.ValidationError(_('Passwords don\'t match'))
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(
commit=False
)
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
......
......@@ -3,11 +3,8 @@ from django.core.management.base import BaseCommand
class CustomBaseCommand(BaseCommand):
def out(self, text, style='s'):
switcher = {
's': 'SUCCESS',
'w': 'WARNING',
'e': 'ERROR',
'n': 'NOTICE',
}.get(style, 's')
switcher = {'s': 'SUCCESS', 'w': 'WARNING', 'e': 'ERROR', 'n': 'NOTICE'}.get(
style, 's'
)
writer = getattr(self.style, switcher)
self.stdout.write(writer(text))
......@@ -8,9 +8,7 @@ from django.core.management.base import CommandError
from django.utils.text import capfirst
from ..base import CustomBaseCommand
from ..template_structures import (
application as application_templates,
)
from ..template_structures import application as application_templates
TEMPLATE_MODELS_INIT = """# isort:skip_file
# flake8: noqa
......@@ -100,17 +98,10 @@ class Command(CustomBaseCommand):
'`applications/` directory.'
)
missing_args_message = (
'You must provide an application name.'
)
missing_args_message = 'You must provide an application name.'
def add_arguments(self, parser):
parser.add_argument(
'name',
nargs=1,
type=str,
help='Name of your application',
)
parser.add_argument('name', nargs=1, type=str, help='Name of your application')
def handle(self, *args, **options):
app_name = options.pop('name')[0]
......@@ -126,15 +117,9 @@ class Command(CustomBaseCommand):
% app_name # noqa: C812
)
applications_dir = os.path.join(
settings.BASE_DIR, 'applications'
)
templates_dir = os.path.join(
settings.BASE_DIR, 'templates'
)
new_application_dir = os.path.join(
applications_dir, app_name
)
applications_dir = os.path.join(settings.BASE_DIR, 'applications')
templates_dir = os.path.join(settings.BASE_DIR, 'templates')
new_application_dir = os.path.join(applications_dir, app_name)
render_params = dict(
app_name_title=app_name.title(),
......@@ -143,75 +128,39 @@ class Command(CustomBaseCommand):
)
self.mkdir(new_application_dir)
self.touch(
os.path.join(new_application_dir, '__init__.py')
)
self.touch(os.path.join(new_application_dir, '__init__.py'))
for package in APP_DIR_STRUCTURE.get('packages'):
package_dir = os.path.join(
new_application_dir, package.get('name')
)
package_dir = os.path.join(new_application_dir, package.get('name'))
self.mkdir(package_dir)
self.touch(
os.path.join(package_dir, '__init__.py')
)
self.touch(os.path.join(package_dir, '__init__.py'))
if package.get('files', False):
self.generate_files(
package.get('files'),
package_dir,
render_params,
)
self.generate_files(package.get('files'), package_dir, render_params)
for template in APP_DIR_STRUCTURE.get('templates'):
template_dir = os.path.join(
templates_dir, app_name
)
template_html_path = os.path.join(
template_dir, template.get('name')
)
template_dir = os.path.join(templates_dir, app_name)
template_html_path = os.path.join(template_dir, template.get('name'))
self.mkdir(template_dir)
self.touch(template_html_path)
if template.get('render', False):
rendered_content = template.get(
'render'
).format(**render_params)
self.create_file_with_content(
template_html_path, rendered_content
)
rendered_content = template.get('render').format(**render_params)
self.create_file_with_content(template_html_path, rendered_content)
self.generate_files(
APP_DIR_STRUCTURE.get('files'),
new_application_dir,
render_params,
APP_DIR_STRUCTURE.get('files'), new_application_dir, render_params
)
self.stdout.write(
self.style.SUCCESS(
'"{0}" application created.'.format(
app_name
)
)
)
self.stdout.write(
self.style.NOTICE(
USER_REMINDER.format(app_name=app_name)
)
self.style.SUCCESS('"{0}" application created.'.format(app_name))
)
self.stdout.write(self.style.NOTICE(USER_REMINDER.format(app_name=app_name)))
def generate_files(
self, files_list, root_path, render_params
):
def generate_files(self, files_list, root_path, render_params):
for single_file in files_list:
file_path = os.path.join(
root_path, single_file.get('name')
)
file_path = os.path.join(root_path, single_file.get('name'))
self.touch(file_path)
if single_file.get('render', False):
rendered_content = single_file.get(
'render'
).format(**render_params)
self.create_file_with_content(
file_path, rendered_content
)
rendered_content = single_file.get('render').format(**render_params)
self.create_file_with_content(file_path, rendered_content)
def mkdir(self, dirname):
try:
......
......@@ -43,31 +43,17 @@ USER_REMINDER = """
class Command(BaseCommand):
help = 'Creates models/MODEL.py, admin/MODEL.py for given application' # noqa: A003
MODEL_TYPE_CHOISES = [
'django',
'basemodel',
'softdelete',
]
def create_or_modify_file(
self, filename, content, mode='w'
):
MODEL_TYPE_CHOISES = ['django', 'basemodel', 'softdelete']
def create_or_modify_file(self, filename, content, mode='w'):
with open(filename, mode) as f:
f.write(content)
def add_arguments(self, parser):
parser.add_argument(
'app_name',
nargs=1,
type=str,
help='Name of your application',
)
parser.add_argument(
'model_name',
nargs=1,
type=str,
help='Name of your model',
'app_name', nargs=1, type=str, help='Name of your application'
)
parser.add_argument('model_name', nargs=1, type=str, help='Name of your model')
parser.add_argument(
'model_type',
nargs='?',
......@@ -85,109 +71,70 @@ class Command(BaseCommand):
import_module(app_name)
except ImportError:
raise CommandError(
'%s is not exists. Please pass existing application name.'
% app_name
'%s is not exists. Please pass existing application name.' % app_name
)
if model_name.lower() in [
model.__name__.lower()
for model in apps.get_app_config(
app_name
).get_models()
for model in apps.get_app_config(app_name).get_models()
]:
raise CommandError(
'%s model is already exists in %s. Please try non-existing model name.'
% (model_name, app_name)
)
app_dir = os.path.join(
settings.BASE_DIR, 'applications', app_name
)
app_dir = os.path.join(settings.BASE_DIR, 'applications', app_name)
dash_seperated_file_base_name = '_'.join(
[
m
for m in re.split(
'([A-Z][a-z]+)', model_name
)
if m
]
[m for m in re.split('([A-Z][a-z]+)', model_name) if m]
)
model_file = os.path.join(
app_dir,
'models',
'{0}.py'.format(
dash_seperated_file_base_name.lower()
),
)
model_init_file = os.path.join(
app_dir, 'models', '__init__.py'
app_dir, 'models', '{0}.py'.format(dash_seperated_file_base_name.lower())
)
model_init_file = os.path.join(app_dir, 'models', '__init__.py')
admin_file = os.path.join(
app_dir,
'admin',
'{0}.py'.format(
dash_seperated_file_base_name.lower()
),
)
admin_init_file = os.path.join(
app_dir, 'admin', '__init__.py'
app_dir, 'admin', '{0}.py'.format(dash_seperated_file_base_name.lower())
)
admin_init_file = os.path.join(app_dir, 'admin', '__init__.py')
content_model_file = TEMPLATE_MODELS[
model_type
].format(model_name=model_name, app_name=app_name)
content_model_file = TEMPLATE_MODELS[model_type].format(
model_name=model_name, app_name=app_name
)
content_init_file = 'from .{0} import *\n'.format(
dash_seperated_file_base_name.lower()
)
content_admin_file = TEMPLATE_ADMINS[
model_type
].format(model_name=model_name, app_name=app_name)
self.create_or_modify_file(
model_file, content_model_file
content_admin_file = TEMPLATE_ADMINS[model_type].format(
model_name=model_name, app_name=app_name
)
self.create_or_modify_file(model_file, content_model_file)
self.stdout.write(
self.style.SUCCESS(
'models/{0} created.'.format(
os.path.basename(model_file)
)
'models/{0} created.'.format(os.path.basename(model_file))
)
)
self.create_or_modify_file(
admin_file, content_admin_file
)
self.create_or_modify_file(admin_file, content_admin_file)
self.stdout.write(
self.style.SUCCESS(
'admin/{0} created.'.format(
os.path.basename(admin_file)
)
'admin/{0} created.'.format(os.path.basename(admin_file))
)
)
self.create_or_modify_file(
model_init_file, content_init_file, 'a'
)
self.create_or_modify_file(model_init_file, content_init_file, 'a')
self.stdout.write(
self.style.SUCCESS(
'{0} model added to models/__init__.py'.format(
model_name
)
'{0} model added to models/__init__.py'.format(model_name)
)
)
self.create_or_modify_file(
admin_init_file, content_init_file, 'a'
)
self.create_or_modify_file(admin_init_file, content_init_file, 'a')
self.stdout.write(
self.style.SUCCESS(
'{0} model added to admin/__init__.py'.format(
model_name
)
'{0} model added to admin/__init__.py'.format(model_name)
)
)
......
# isort:skip_file
# flake8: noqa
from .models import *
from .admins import *
# isort:skip_file
# flake8: noqa
from .basemodel import *
from .django import *
from .softdelete import *
# isort:skip_file
# flake8: noqa
from .html import *
from .apps import *
from .urls import *
......
TEMPLATE_HTML = """{{% extends "base.html" %}}
{{% load static %}}
{{% load i18n %}}
{{% load static i18n %}}
{{% block title %}}{app_name_title} Application{{% endblock %}}
......
# isort:skip_file
# flake8: noqa
from .basemodel import *
from .django import *
from .softdelete import *
......@@ -3,17 +3,11 @@ from django.utils.translation import ugettext_lazy as _
from baseapp.models import BaseModel
# fmt: off
__all__ = [
'{model_name}',
]
__all__ = ['{model_name}']
class {model_name}(BaseModel):
title = models.CharField(
max_length=255,
verbose_name=_('title'),
)
title = models.CharField(max_length=255, verbose_name=_('title'))
class Meta:
app_label = '{app_name}'
......@@ -22,7 +16,6 @@ class {model_name}(BaseModel):
def __str__(self):
return self.title
# fmt: on
"""
......
TEMPLATE_MODEL_DJANGO = """from django.db import models
from django.utils.translation import ugettext_lazy as _
# fmt: off
__all__ = [
'{model_name}',
]
__all__ = ['{model_name}']
class {model_name}(models.Model):
created_at = models.DateTimeField(
auto_now_add=True,
verbose_name=_('Created At'),
)
updated_at = models.DateTimeField(
auto_now=True,
verbose_name=_('Updated At'),
)
title = models.CharField(
max_length=255,
verbose_name=_('title'),
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at'))
updated_at = models.DateTimeField(auto_now=True, verbose_name=_('updated at'))
title = models.CharField(max_length=255, verbose_name=_('title'))
class Meta:
app_label = '{app_name}'
......@@ -28,7 +16,6 @@ class {model_name}(models.Model):
def __str__(self):
return self.title
# fmt: on
"""
......
......@@ -3,17 +3,11 @@ from django.utils.translation import ugettext_lazy as _
from baseapp.models import BaseModelWithSoftDelete
# fmt: off
__all__ = [
'{model_name}',
]
__all__ = ['{model_name}']
class {model_name}(BaseModelWithSoftDelete):
title = models.CharField(
max_length=255,
verbose_name=_('title'),
)
title = models.CharField(max_length=255, verbose_name=_('title'))
class Meta:
app_label = '{app_name}'
......@@ -22,7 +16,6 @@ class {model_name}(BaseModelWithSoftDelete):
def __str__(self):
return self.title
# fmt: on
"""
......
from .locale import * # noqa
# isort:skip_file
# flake8: noqa
from .locale import *
......@@ -34,8 +34,6 @@ class CustomLocaleMiddleware(object):
response = self.get_response(request)
patch_vary_headers(response, ('Accept-Language',))
response[
'Content-Language'
] = translation.get_language()
response['Content-Language'] = translation.get_language()
translation.deactivate()
return response
from .html_debug import * # noqa
# isort:skip_file
# flake8: noqa
from .html_debug import *
# isort:skip_file
# flake8: noqa
from .base import *
from .user import *
......@@ -60,19 +60,13 @@ class BaseModelWithSoftDeleteQuerySet(BaseModelQuerySet):
)
def actives(self):
return self.all().filter(
status=BaseModel.STATUS_ONLINE
)
return self.all().filter(status=BaseModel.STATUS_ONLINE)
def offlines(self):
return self.all().filter(
status=BaseModel.STATUS_OFFLINE
)
return self.all().filter(status=BaseModel.STATUS_OFFLINE)
def drafts(self):
return self.all().filter(
status=BaseModel.STATUS_DRAFT
)
return self.all().filter(status=BaseModel.STATUS_DRAFT)
def delete(self):
return self._delete_or_undelete()
......@@ -88,22 +82,13 @@ class BaseModelWithSoftDeleteQuerySet(BaseModelQuerySet):
call_method = 'undelete' if undelete else 'delete'
for model_instance in self:
_count, model_information = getattr(
model_instance, call_method
)()
for (
app_label,
row_amount,
) in model_information.items():
_count, model_information = getattr(model_instance, call_method)()
for (app_label, row_amount) in model_information.items():
processed_instances.setdefault(app_label, 0)
processed_instances[app_label] = (
processed_instances[app_label]
+ row_amount
processed_instances[app_label] + row_amount
)
return (
sum(processed_instances.values()),
processed_instances,
)
return (sum(processed_instances.values()), processed_instances)
class BaseModelManager(models.Manager):
......@@ -129,9 +114,7 @@ class BaseModelWithSoftDeleteManager(BaseModelManager):
"""
def get_queryset(self):
return BaseModelWithSoftDeleteQuerySet(
self.model, using=self._db
)
return BaseModelWithSoftDeleteQuerySet(self.model, using=self._db)
def all(self): # noqa: A003
return self.get_queryset().all()
......@@ -163,16 +146,10 @@ class BaseModel(models.Model):
(STATUS_DRAFT, _('Draft')),
)
created_at = models.DateTimeField(
auto_now_add=True, verbose_name=_('Created At')
)
updated_at = models.DateTimeField(
auto_now=True, verbose_name=_('Updated At')
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('Created At'))
updated_at = models.DateTimeField(auto_now=True, verbose_name=_('Updated At'))
status = models.IntegerField(
choices=STATUS_CHOICES,
default=STATUS_ONLINE,
verbose_name=_('Status'),
choices=STATUS_CHOICES, default=STATUS_ONLINE, verbose_name=_('Status')
)
objects = BaseModelManager()
......@@ -205,19 +182,11 @@ class BaseModelWithSoftDelete(BaseModel):
processed_instances = {}
call_method = 'undelete' if undelete else 'delete'
log_params = {
'instance': self,
'label': self._meta.label,
'pk': self.pk,
}
log_message = (
'{action} on: "{instance} - pk: {pk}" [{label}]'
)
log_params = {'instance': self, 'label': self._meta.label, 'pk': self.pk}
log_message = '{action} on: "{instance} - pk: {pk}" [{label}]'
if call_method == 'delete':
models.signals.pre_delete.send(
sender=self.__class__, instance=self
)
models.signals.pre_delete.send(sender=self.__class__, instance=self)
status_value = self.STATUS_DELETED
deleted_at_value = timezone.now()
log_params.update(action='Soft-delete')
......@@ -233,43 +202,29 @@ class BaseModelWithSoftDelete(BaseModel):
self.save()
if call_method == 'delete':
models.signals.post_delete.send(
sender=self.__class__, instance=self
)
models.signals.post_delete.send(sender=self.__class__, instance=self)
processed_instances.update({self._meta.label: 1})
for related_object in self._meta.related_objects:
if (
hasattr(related_object, 'on_delete')
and getattr(related_object, 'on_delete')
== models.CASCADE
and getattr(related_object, 'on_delete') == models.CASCADE
):
accessor_name = (
related_object.get_accessor_name()
)
related_model_instances = getattr(
self, accessor_name
)
accessor_name = related_object.get_accessor_name()
related_model_instances = getattr(self, accessor_name)
related_model_instance_count = 0
related_model_query = (
related_model_instances.all()
)
if call_method == 'undelete':
related_model_query = (
related_model_instances.deleted()
)
related_model_query = related_model_instances.all()
if call_method == 'undelete' and hasattr(
related_model_instances, 'deleted'
):
related_model_query = related_model_instances.deleted()
for (
related_model_instance
) in related_model_query:
getattr(
related_model_instance, call_method
)()
for related_model_instance in related_model_query:
getattr(related_model_instance, call_method)()
processed_instances.setdefault(
related_model_instance._meta.label,
related_model_instance_count,
related_model_instance._meta.label, related_model_instance_count
)
related_model_instance_count += 1
processed_instances.update(
......@@ -277,7 +232,4 @@ class BaseModelWithSoftDelete(BaseModel):
related_model_instance._meta.label: related_model_instance_count
}
)
return (
sum(processed_instances.values()),
processed_instances,
)
return (sum(processed_instances.values()), processed_instances)
......@@ -23,17 +23,10 @@ class UserManager(BaseUserManager):
use_in_migrations = True
def create_user(
self,
email,
first_name,
last_name,
middle_name=None,
password=None,
self, email, first_name, last_name, middle_name=None, password=None
):
if not email:
raise ValueError(
_('Users must have an email address')
)
raise ValueError(_('Users must have an email address'))
user_create_fields = {
'email': email,
......@@ -47,39 +40,22 @@ class UserManager(BaseUserManager):
user = self.model(**user_create_fields)
user.set_password(password)
user.save(using=self._db)
logger.info(
f'{user.get_full_name()} created successfully. PK: {user.pk}'
)
logger.info(f'{user.get_full_name()} created successfully. PK: {user.pk}')
return user
def create_superuser(
self,
email,
first_name,
last_name,
middle_name=None,
password=None,
self, email, first_name, last_name, middle_name=None, password=None
):
user = self.create_user(
email,
first_name,
last_name,
middle_name,
password,
)
user = self.create_user(email, first_name, last_name, middle_name, password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
logger.info(
f'{user.get_full_name()} is set to superuser. PK: {user.pk}'
)
logger.info(f'{user.get_full_name()} is set to superuser. PK: {user.pk}')
return user
def save_user_avatar(instance, filename):
return custom_save_file(
instance, filename, upload_to='avatar/'
)
return custom_save_file(instance, filename, upload_to='avatar/')
class User(AbstractBaseUser, PermissionsMixin):
......@@ -87,39 +63,22 @@ class User(AbstractBaseUser, PermissionsMixin):
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
created_at = models.DateTimeField(
auto_now_add=True, verbose_name=_('Created At')
)
updated_at = models.DateTimeField(
auto_now=True, verbose_name=_('Updated At')
)
email = models.EmailField(
unique=True, verbose_name=_('email address')
)
first_name = models.CharField(
max_length=255, verbose_name=_('first name')
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('Created At'))
updated_at = models.DateTimeField(auto_now=True, verbose_name=_('Updated At'))
email = models.EmailField(unique=True, verbose_name=_('email address'))
first_name = models.CharField(max_length=255, verbose_name=_('first name'))
middle_name = models.CharField(
max_length=255,
null=True,
blank=True,
verbose_name=_('middle name'),
)
last_name = models.CharField(
max_length=255, verbose_name=_('last name')
max_length=255, null=True, blank=True, verbose_name=_('middle name')
)
last_name = models.CharField(max_length=255, verbose_name=_('last name'))
avatar = models.FileField(
upload_to=save_user_avatar,
verbose_name=_('Profile Image'),
null=True,
blank=True,
)
is_active = models.BooleanField(
default=True, verbose_name=_('active')
)
is_staff = models.BooleanField(
default=False, verbose_name=_('staff status')
)
is_active = models.BooleanField(default=True, verbose_name=_('active'))
is_staff = models.BooleanField(default=False, verbose_name=_('staff status'))
objects = UserManager()
......@@ -141,12 +100,8 @@ class User(AbstractBaseUser, PermissionsMixin):
'last_name': self.last_name,
}
if self.middle_name:
params[
'middle_name'
] = ' {middle_name} '.format(
params['middle_name'] = ' {middle_name} '.format(
middle_name=self.middle_name
)
full_name = '{first_name}{middle_name}{last_name}'.format(
**params
)
full_name = '{first_name}{middle_name}{last_name}'.format(**params)
return full_name.strip()
......@@ -25,9 +25,7 @@ class Category(BaseModelWithSoftDelete):
class Post(BaseModelWithSoftDelete):
category = models.ForeignKey(
to='Category',
on_delete=models.CASCADE,
related_name='posts',
to='Category', on_delete=models.CASCADE, related_name='posts'
)
title = models.CharField(max_length=255)
......
......@@ -6,27 +6,20 @@ from .base_models import BasicPost
class BaseModelTestCase(TestCase):
@classmethod
def setUpTestData(cls): # noqa: N802
cls.post = BasicPost.objects.create(
title='Test Post 1'
)
cls.post = BasicPost.objects.create(title='Test Post 1')
cls.post_status_deleted = BasicPost.objects.create(
title='Test Post 2',
status=BasicPost.STATUS_DELETED,
title='Test Post 2', status=BasicPost.STATUS_DELETED
)
cls.post_status_offline = BasicPost.objects.create(
title='Test Post 3',
status=BasicPost.STATUS_OFFLINE,
title='Test Post 3', status=BasicPost.STATUS_OFFLINE
)
cls.post_status_draft = BasicPost.objects.create(
title='Test Post 4',
status=BasicPost.STATUS_DRAFT,
title='Test Post 4', status=BasicPost.STATUS_DRAFT
)
def test_basemodel_fields(self):
self.assertEqual(self.post.pk, self.post.id)
self.assertEqual(
self.post.status, BasicPost.STATUS_ONLINE
)
self.assertEqual(self.post.status, BasicPost.STATUS_ONLINE)
def test_basemodel_queryset(self):
self.assertQuerysetEqual(
......@@ -39,18 +32,14 @@ class BaseModelTestCase(TestCase):
],
)
self.assertQuerysetEqual(
BasicPost.objects.actives().order_by('id'),
['<BasicPost: Test Post 1>'],
BasicPost.objects.actives().order_by('id'), ['<BasicPost: Test Post 1>']
)
self.assertQuerysetEqual(
BasicPost.objects.offlines(),
['<BasicPost: Test Post 3>'],
BasicPost.objects.offlines(), ['<BasicPost: Test Post 3>']
)
self.assertQuerysetEqual(
BasicPost.objects.deleted(),
['<BasicPost: Test Post 2>'],
BasicPost.objects.deleted(), ['<BasicPost: Test Post 2>']
)
self.assertQuerysetEqual(
BasicPost.objects.drafts(),
['<BasicPost: Test Post 4>'],
BasicPost.objects.drafts(), ['<BasicPost: Test Post 4>']
)
......@@ -9,60 +9,33 @@ class BaseModelWithSoftDeleteTestCase(TestCase):
category = Category.objects.create(title='Python')
cls.category = category
cls.posts = [
Post.objects.create(
category=category, title='Python post 1'
),
Post.objects.create(
category=category, title='Python post 2'
),
Post.objects.create(category=category, title='Python post 1'),
Post.objects.create(category=category, title='Python post 2'),
]
def test_basemodelwithsoftdelete_fields(self):
self.assertEqual(self.category.pk, self.category.id)
self.assertEqual(
self.category.status, Post.STATUS_ONLINE
)
self.assertEqual(self.category.status, Post.STATUS_ONLINE)
for post in self.posts:
self.assertEqual(
post.status, Post.STATUS_ONLINE
)
self.assertEqual(post.status, Post.STATUS_ONLINE)
def test_basemodelwithsoftdelete_queryset(self):
self.assertQuerysetEqual(
self.category.posts.all().order_by('id'),
[
'<Post: Python post 1>',
'<Post: Python post 2>',
],
)
self.assertQuerysetEqual(
Category.objects.actives(),
['<Category: Python>'],
)
self.assertQuerysetEqual(
Category.objects.offlines(), []
)
self.assertQuerysetEqual(
Category.objects.deleted(), []
)
self.assertQuerysetEqual(
Category.objects.drafts(), []
['<Post: Python post 1>', '<Post: Python post 2>'],
)
self.assertQuerysetEqual(Category.objects.actives(), ['<Category: Python>'])
self.assertQuerysetEqual(Category.objects.offlines(), [])
self.assertQuerysetEqual(Category.objects.deleted(), [])
self.assertQuerysetEqual(Category.objects.drafts(), [])
def test_softdelete(self):
deleted_category = self.category.delete()
self.assertEqual(
deleted_category,
(3, {'baseapp.Category': 1, 'baseapp.Post': 2}),
)
self.assertQuerysetEqual(
Category.objects.deleted(),
['<Category: Python>'],
deleted_category, (3, {'baseapp.Category': 1, 'baseapp.Post': 2})
)
self.assertQuerysetEqual(Category.objects.deleted(), ['<Category: Python>'])
self.assertQuerysetEqual(
Post.objects.deleted().order_by('id'),
[
'<Post: Python post 1>',
'<Post: Python post 2>',
],
['<Post: Python post 1>', '<Post: Python post 2>'],
)
# isort:skip_file
# flake8: noqa
from .console import *
from .numerify import *
from .urlify import *
......
......@@ -11,9 +11,7 @@ try:
except BaseException:
pass
TERMINAL_COLUMNS, TERMINAL_LINES = (
shutil.get_terminal_size()
)
TERMINAL_COLUMNS, TERMINAL_LINES = shutil.get_terminal_size()
__all__ = ['console']
......@@ -83,15 +81,7 @@ class Console:
valid_options = ['source', 'width', 'indent', 'color']
available_colors = dict(
black=0,
red=1,
green=2,
yellow=3,
blue=4,
magenta=5,
cyan=6,
white=7,
default=8,
black=0, red=1, green=2, yellow=3, blue=4, magenta=5, cyan=6, white=7, default=8
)
defaults_options = {
......@@ -106,10 +96,7 @@ class Console:
def __init__(self, **options):
self.options = {}
for (
default_option,
default_value,
) in self.defaults_options.items():
for (default_option, default_value) in self.defaults_options.items():
self.options[default_option] = default_value
self.configure(**options)
......@@ -118,15 +105,11 @@ class Console:
if option in self.valid_options:
self.options[option] = value
else:
raise Exception(
f'Invalid option: [{option}] passed'
)
raise Exception(f'Invalid option: [{option}] passed')
color = self.options['color']
if color not in self.available_colors.keys():
raise Exception(
f'Invalid color value: [{color}] passed'
)
raise Exception(f'Invalid color value: [{color}] passed')
if not isinstance(self.options['width'], int):
raise Exception(
......@@ -144,9 +127,7 @@ class Console:
def colorize(self, input_string):
return '\033[3{0}m{1}{2}'.format(
self.available_colors[self.options['color']],
input_string,
'\033[0m',
self.available_colors[self.options['color']], input_string, '\033[0m'
)
def __call__(self, *args, **options):
......@@ -159,16 +140,12 @@ class Console:
source_name = arg.__class__.__name__
if source_name != 'type':
source_name = 'instance of {0}'.format(
source_name
)
source_name = 'instance of {0}'.format(source_name)
if hasattr(arg, '__name__'):
source_name = arg.__name__
source = '{0} | {1}'.format(
source_name, type(arg)
)
source = '{0} | {1}'.format(source_name, type(arg))
public_attributes = []
internal_methods = []
......@@ -183,13 +160,9 @@ class Console:
public_attributes.append(object_method)
if public_attributes:
out.update(
public_attributes=public_attributes
)
out.update(public_attributes=public_attributes)
if internal_methods:
out.update(
internal_methods=internal_methods
)
out.update(internal_methods=internal_methods)
if private_methods:
out.update(private_methods=private_methods)
......@@ -199,79 +172,49 @@ class Console:
class_methods = []
public_methods = []
for (
obj_attr,
obj_attr_val,
) in arg.__dict__.items():
for (obj_attr, obj_attr_val) in arg.__dict__.items():
_name = type(obj_attr_val).__name__
if _name == 'property':
property_list.append(obj_attr)
if obj_attr in public_attributes:
public_attributes.remove(
obj_attr
)
public_attributes.remove(obj_attr)
if _name == 'staticmethod':
static_methods.append(obj_attr)
if obj_attr in public_attributes:
public_attributes.remove(
obj_attr
)
public_attributes.remove(obj_attr)
if _name == 'classmethod':
class_methods.append(obj_attr)
if obj_attr in public_attributes:
public_attributes.remove(
obj_attr
)
public_attributes.remove(obj_attr)
if _name == 'function':
public_methods.append(obj_attr)
if obj_attr in internal_methods:
internal_methods.remove(
obj_attr
)
internal_methods.remove(obj_attr)
if obj_attr in public_attributes:
public_attributes.remove(
obj_attr
)
public_attributes.remove(obj_attr)
if property_list:
out.update(property_list=property_list)
if static_methods:
out.update(
static_methods=static_methods
)
out.update(static_methods=static_methods)
if class_methods:
out.update(class_methods=class_methods)
if public_methods:
out.update(
public_methods=public_methods
)
out.update(public_methods=public_methods)
if not arg.__dict__.get('__init__', False):
instance_attributes = []
for instance_attr in list(
arg.__dict__.keys()
):
instance_attributes.append(
instance_attr
)
if (
instance_attr
in public_attributes
):
public_attributes.remove(
instance_attr
)
for instance_attr in list(arg.__dict__.keys()):
instance_attributes.append(instance_attr)
if instance_attr in public_attributes:
public_attributes.remove(instance_attr)
if instance_attr in public_methods:
public_methods.remove(
instance_attr
)
out.update(
instance_attributes=instance_attributes
)
public_methods.remove(instance_attr)
out.update(instance_attributes=instance_attributes)
options.update(source=source)
self.oprint(out, **options)
......@@ -280,16 +223,12 @@ class Console:
source = self.options['source']
if 'source' in options.keys():
source = '{0} : {1}'.format(
source, options.pop('source')
)
source = '{0} : {1}'.format(source, options.pop('source'))
self.configure(**options)
self.pp = pprint.PrettyPrinter(
indent=self.options['indent'],
width=self.options['width'],
compact=True,
indent=self.options['indent'], width=self.options['width'], compact=True
)
header = self.options['seperator_line'].format(
......@@ -297,10 +236,7 @@ class Console:
char=self.options['seperator_char'],
width=self.options['width'],
)
footer = (
self.options['seperator_char']
* self.options['width']
)
footer = self.options['seperator_char'] * self.options['width']
sys.stdout.write(self.colorize(header))
sys.stdout.write('\n')
......
......@@ -8,9 +8,7 @@ from baseapp.utils import urlify
__all__ = ['save_file']
def save_file(
instance, filename, upload_to='upload/%Y/%m/%d/'
):
def save_file(instance, filename, upload_to='upload/%Y/%m/%d/'):
"""
By default, this saves to : `MEDIA_ROOT/upload/2017/09/06/`
......@@ -35,15 +33,11 @@ def save_file(
"""
file_basename, file_extension = os.path.splitext(
filename
)
file_basename, file_extension = os.path.splitext(filename)
file_savename = '{safe_basename}{extension}'.format(
safe_basename=slugify(urlify(file_basename)),
extension=file_extension.lower(),
safe_basename=slugify(urlify(file_basename)), extension=file_extension.lower()
)
now = datetime.datetime.now()
return '{upload_to}{file_savename}'.format(
upload_to=now.strftime(upload_to),
file_savename=file_savename,
upload_to=now.strftime(upload_to), file_savename=file_savename
)
......@@ -42,12 +42,7 @@ def urlify(value, language='tr'):
"""
return ''.join(
map(
lambda char: LETTER_TRANSFORM_MAP[language].get(
char, char
),
iter(value),
)
map(lambda char: LETTER_TRANSFORM_MAP[language].get(char, char), iter(value))
).lower()
......
# isort:skip_file
# flake8: noqa
from .index import *
......@@ -16,11 +16,7 @@ class IndexView(HtmlDebugMixin, TemplateView):
self.hdbg('This', 'is', 'an', 'example', 'of')
self.hdbg('self.hdbg', 'usage')
self.hdbg(self.request.META)
self.hdbg(
slugify(
urlify('Merhaba Dünya! Ben Uğur Özyılmazel')
)
)
self.hdbg(slugify(urlify('Merhaba Dünya! Ben Uğur Özyılmazel')))
kwargs = super().get_context_data(**kwargs)
query_string_p = numerify(self.request.GET.get('p'))
......
from .image_file import * # noqa
# isort:skip_file
# flake8: noqa
from .image_file import *
import os
import sys
BASE_DIR = os.path.dirname(
os.path.dirname(
os.path.dirname(os.path.abspath(__file__))
)
)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
SECRET_KEY = os.environ.get('DJANGO_SECRET')
sys.path.append(os.path.join(BASE_DIR, 'applications'))
......
......@@ -16,9 +16,7 @@ DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join( # noqa: F405
BASE_DIR, # noqa: F405
'db',
'development.sqlite3', # noqa: F405
BASE_DIR, 'db', 'development.sqlite3' # noqa: F405 # noqa: F405
),
}
}
......@@ -26,21 +24,11 @@ DATABASES = {
# uncomment for PostgreSQL
# DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql', 'NAME': 'NAME_OF_YOUR_DB'}}
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'), # noqa: F405
)
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),) # noqa: F405
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # noqa: F405
WERKZUEG_FILTER_EXTENSTIONS = [
'css',
'js',
'png',
'jpg',
'svg',
'gif',
'woff',
]
WERKZUEG_FILTER_EXTENSTIONS = ['css', 'js', 'png', 'jpg', 'svg', 'gif', 'woff']
LOGGING = {
'version': 1,
......@@ -80,10 +68,7 @@ LOGGING = {
'level': 'DEBUG',
'propagate': True,
},
'app': {
'handlers': ['console_custom'],
'level': 'DEBUG',
},
'app': {'handlers': ['console_custom'], 'level': 'DEBUG'},
# enable this block if you want to see SQL queries :)
# 'django.db.backends': {
# 'handlers': ['console_sql'],
......@@ -93,9 +78,7 @@ LOGGING = {
}
# middlewares for development purposes only
MIDDLEWARE += [ # noqa: F405
'debug_toolbar.middleware.DebugToolbarMiddleware'
]
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware'] # noqa: F405
# apps for development purposes only
INSTALLED_APPS += ['debug_toolbar'] # noqa: F405
......@@ -12,36 +12,21 @@ ALLOWED_HOSTS = [
]
DATABASES = {'default': db_from_env}
SECURE_PROXY_SSL_HEADER = (
'HTTP_X_FORWARDED_PROTO',
'https',
)
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'
},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
]
STATICFILES_STORAGE = (
'whitenoise.django.GzipManifestStaticFilesStorage'
)
STATIC_ROOT = os.path.join( # noqa: F405
BASE_DIR, 'staticfiles' # noqa: F405
)
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # noqa: F405 # noqa: F405
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'), # noqa: F405
)
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),) # noqa: F405
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # noqa: F405
# fmt: off
......@@ -57,18 +42,14 @@ MIDDLEWARE.insert( # noqa: F405
# fmt: on
LOGGING_CONFIG = None
LOGLEVEL = os.environ.get( # noqa: F405
'LOGLEVEL', 'info'
).upper()
LOGLEVEL = os.environ.get('LOGLEVEL', 'info').upper() # noqa: F405
logging.config.dictConfig(
{
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'default': {
'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
}
'default': {'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
},
'handlers': {
'mail_admins': {
......@@ -90,11 +71,7 @@ logging.config.dictConfig(
},
'loggers': {
'': {'level': 'DEBUG', 'handlers': ['stdout']},
'app': {
'level': LOGLEVEL,
'handlers': ['stdout'],
'propagate': False,
},
'app': {'level': LOGLEVEL, 'handlers': ['stdout'], 'propagate': False},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
......
......@@ -2,15 +2,8 @@ from .base import * # noqa pylint: disable=E0401
SECRET_KEY = 'fake-key'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}}
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.MD5PasswordHasher',
)
PASSWORD_HASHERS = ('django.contrib.auth.hashers.MD5PasswordHasher',)
MIGRATION_MODULES = {'baseapp': None}
......@@ -2,15 +2,8 @@ from .base import * # noqa pylint: disable=E0401
SECRET_KEY = 'fake-key'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}}
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.MD5PasswordHasher',
)
PASSWORD_HASHERS = ('django.contrib.auth.hashers.MD5PasswordHasher',)
MIGRATION_MODULES = {'baseapp': None}
......@@ -3,10 +3,7 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault(
'DJANGO_SETTINGS_MODULE',
'config.settings.{0}'.format(
os.environ.get('DJANGO_ENV')
),
'DJANGO_SETTINGS_MODULE', 'config.settings.{0}'.format(os.environ.get('DJANGO_ENV'))
)
application = get_wsgi_application()
......@@ -18,9 +18,10 @@ color_8=$(tput setaf 8) # gray
color_r=$(tput sgr0) # reset
AVAILABLE_OPTIONS=(
"Django 2.1.7"
"Django 2.1.5"
"Django 2.0.5"
"Django 2.1.3"
"Django 2.0.5"
"Cancel and quit"
)
......@@ -29,18 +30,22 @@ PS3="Select option:"
select i in "${AVAILABLE_OPTIONS[@]}"
do
case $i in
"Django 2.1.5")
PACKAGE="django-2.1.5"
"Django 2.1.7")
PACKAGE="django-2.1.7"
break
;;
"Django 2.0.5")
PACKAGE="django-2.0.5"
"Django 2.1.5")
PACKAGE="django-2.1.5"
break
;;
"Django 2.1.3")
PACKAGE="django-2.1.3"
break
;;
"Django 2.0.5")
PACKAGE="django-2.0.5"
break
;;
"Cancel and quit")
echo "Canceled..."
exit 1
......
# isort:skip_file
# flake8: noqa
from .formatters import *
from .werkzueg_filters import *
......@@ -3,10 +3,7 @@ import re
from django.core.management.color import color_style
__all__ = [
'CustomWerkzeugLogFormatter',
'CustomSqlLogFormatter',
]
__all__ = ['CustomWerkzeugLogFormatter', 'CustomSqlLogFormatter']
ansi_escape = re.compile(r'\x1b[^m]*m')
......@@ -45,9 +42,7 @@ class CustomWerkzeugLogFormatter(logging.Formatter):
levelname = record.levelname.lower()
levelstyle = self.style.SUCCESS
record.levelname = '{0:.<14}'.format(
record.levelname
)
record.levelname = '{0:.<14}'.format(record.levelname)
if levelname == 'warning':
levelstyle = self.style.WARNING
......@@ -70,8 +65,6 @@ class CustomSqlLogFormatter(logging.Formatter):
def format(self, record): # noqa: A003
record.levelname = '{0:.<14}'.format('SQL')
record.levelname = self.style.HTTP_INFO(
record.levelname
)
record.levelname = self.style.HTTP_INFO(record.levelname)
record.sql = self.style.SQL_KEYWORD(record.sql)
return super().format(record)
......@@ -4,15 +4,10 @@ __all__ = ['werkzueg_filter_extenstions_callback']
def werkzueg_filter_extenstions_callback(record):
extensions_to_filter = getattr(
settings, 'WERKZUEG_FILTER_EXTENSTIONS', False
)
extensions_to_filter = getattr(settings, 'WERKZUEG_FILTER_EXTENSTIONS', False)
if extensions_to_filter:
return not any(
[
'.{0}'.format(ext) in record.msg
for ext in extensions_to_filter
]
['.{0}'.format(ext) in record.msg for ext in extensions_to_filter]
)
else:
return True
[tool.black]
line-length = 60
line-length = 88
py36 = true
skip-string-normalization = true
quiet = true
......
Django==2.1.5
Django==2.1.7
Pillow==5.4.1
django-extensions==2.1.4
\ No newline at end of file
django-extensions==2.1.6
python-slugify==3.0.0
-r base.pip
ipython==7.1.1
Werkzeug==0.14.1
ipython==7.3.0
Werkzeug==0.15.0
django-debug-toolbar==1.11
coverage==4.5.2
isort==4.3.4
black==18.9b0
flake8==3.6.0
flake8-bandit==2.0.0
coverage==4.5.3
isort==4.3.15
black==19.3b0
flake8==3.7.7
flake8-bandit==2.1.0
flake8-blind-except==0.1.1
flake8-bugbear==18.8.0
flake8-builtins==1.4.1
......
-r base.pip
gunicorn==19.9.0
psycopg2-binary==2.7.6.1
psycopg2-binary==2.7.7
dj-database-url==0.5.0
whitenoise==4.1.2
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment