Skip to content

Commit

Permalink
Merge pull request #12 from mustafaulker/dev/upgrade-py-dj
Browse files Browse the repository at this point in the history
- Upgrade Python and Django syntax
- Format the whole project 
- Update release notes
  • Loading branch information
mustafaulker authored Dec 18, 2024
2 parents 1f8a055 + 829a13c commit 58a8b53
Show file tree
Hide file tree
Showing 51 changed files with 853 additions and 681 deletions.
27 changes: 27 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
default_language_version:
python: python3.12

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks.git
rev: v5.0.0
hooks:
- id: check-merge-conflict

- repo: https://github.com/astral-sh/ruff-pre-commit.git
rev: v0.8.3
hooks:
- id: ruff
args: [ --fix, --unsafe-fixes ]
- id: ruff-format
args: [ -- ]

- repo: https://github.com/asottile/pyupgrade
rev: v3.19.1
hooks:
- id: pyupgrade

- repo: https://github.com/adamchainz/django-upgrade
rev: 1.22.2
hooks:
- id: django-upgrade
args: [ --target-version, "5.0" ]
6 changes: 6 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 6.6.2
- Run pyupgrade and django-upgrade. Format the whole project using pre-commit & ruff

## 6.6.0
- Split files and zip them when the row count exceeds one million.

## 6.5.7
- Remove mis-import

Expand Down
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ Targets sys admins and capable end users who might not be able to program or gai

# News

## 6.6.2
- Run pyupgrade and django-upgrade. Format the whole project using pre-commit & ruff

## 6.6.0
- Split files and zip them when the row count exceeds one million.

## 6.5.7
- Remove mis-import

Expand All @@ -19,14 +25,6 @@ Targets sys admins and capable end users who might not be able to program or gai
- Remove six dependency
- Replace deprecated openpyxl save_virtual_workbook func. (Cherry-picked from @tmszi's fork)

## 6.5.4

- Create AutoField to BigAutoField convertion migration

## 6.5.3

- Fix "Router with basename "report" is already registered" error

## 6.5

- Make compatible for Django >4. Project's GitLab Repo merged into this fork and Django 4 compatibility changes were made.
Expand Down
1 change: 1 addition & 0 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import sys


if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "report_builder_demo.settings")

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-report-builder"
version = "6.6.0"
version = "6.6.2"
description = "Query and Report builder for Django ORM"
authors = ["David Burke <david@burkesoftware.com>"]
packages = [
Expand Down
29 changes: 15 additions & 14 deletions report_builder/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
from django.urls import reverse
from django.utils.safestring import mark_safe

from report_builder.models import Report, Format
from report_builder.models import Format, Report


class StarredFilter(SimpleListFilter):
title = 'Your starred reports'
parameter_name = 'starred'

def lookups(self, request, model_admin):
return (
('Starred', 'Starred Reports'),
)
return (('Starred', 'Starred Reports'),)

def queryset(self, request, queryset):
if self.value() == 'Starred':
Expand All @@ -38,7 +36,9 @@ class ReportAdmin(admin.ModelAdmin):
'download_xlsx',
'copy_report',
)
readonly_fields = ['slug', ]
readonly_fields = [
'slug',
]
fields = ['name', 'description', 'root_model', 'slug']
search_fields = ('name', 'description')
list_filter = (StarredFilter, 'root_model', 'created', 'modified', 'root_model__app_label')
Expand All @@ -55,34 +55,35 @@ class Media:
def response_add(self, request, obj, post_url_continue=None):
if '_easy' in request.POST:
return HttpResponseRedirect(obj.get_absolute_url())
return super(ReportAdmin, self).response_add(request, obj, post_url_continue)
return super().response_add(request, obj, post_url_continue)

def response_change(self, request, obj):
if '_easy' in request.POST:
return HttpResponseRedirect(obj.get_absolute_url())
return super(ReportAdmin, self).response_change(request, obj)
return super().response_change(request, obj)

def change_view(self, request, object_id, extra_context=None):
if getattr(settings, 'REPORT_BUILDER_ASYNC_REPORT', False) and 'report_file' not in self.fields:
self.fields += ['report_file', 'report_file_creation']
return super(ReportAdmin, self).change_view(request, object_id, extra_context=None)
return super().change_view(request, object_id, extra_context=None)

def changelist_view(self, request, extra_context=None):
self.user = request.user
return super(ReportAdmin, self).changelist_view(request, extra_context=extra_context)
return super().changelist_view(request, extra_context=extra_context)

@admin.display(
description="Starred"
description="Starred",
)
def ajax_starred(self, obj):
if obj.starred.filter(id=self.user.id):

img = static('report_builder/img/star.png')
else:
img = static('report_builder/img/unstar.png')
return mark_safe(
'<a href="javascript:void(0)" onclick="ajax_add_star(this, \'{0}\')"><img style="width: 26px; margin: -6px;" src="{1}"/></a>'.format(
reverse('ajax_add_star', args=[obj.id]), img)
'<a href="javascript:void(0)" onclick="ajax_add_star(this, \'{}\')"><img style="width: 26px; margin: -6px;" src="{}"/></a>'.format(
reverse('ajax_add_star', args=[obj.id]),
img,
),
)

def save_model(self, request, obj, form, change):
Expand Down Expand Up @@ -111,7 +112,7 @@ def export_to_report(modeladmin, request, queryset):
selected.append(str(s))
ct = ContentType.objects.get_for_model(queryset.model)
return HttpResponseRedirect(
reverse('export_to_report') + "?ct=%s&admin_url=%s&ids=%s" % (ct.pk, admin_url, ",".join(selected))
reverse('export_to_report') + "?ct={}&admin_url={}&ids={}".format(ct.pk, admin_url, ",".join(selected)),
)


Expand Down
80 changes: 57 additions & 23 deletions report_builder/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from django.db import transaction
from rest_framework import serializers

from report_builder.models import Report, DisplayField, FilterField, Format
from report_builder.models import DisplayField, FilterField, Format, Report


User = get_user_model()

Expand All @@ -19,20 +20,35 @@ class Meta:
class DisplayFieldSerializer(serializers.ModelSerializer):
class Meta:
model = DisplayField
fields = ('id', 'path', 'path_verbose', 'field', 'field_verbose',
'name', 'sort', 'sort_reverse', 'width', 'aggregate',
'position', 'total', 'group', 'report', 'display_format',
'field_type')
fields = (
'id',
'path',
'path_verbose',
'field',
'field_verbose',
'name',
'sort',
'sort_reverse',
'width',
'aggregate',
'position',
'total',
'group',
'report',
'display_format',
'field_type',
)
read_only_fields = ('id',)

def to_internal_value(self, data):
if data.get('sort') is '':
if data.get('sort') == '':
data['sort'] = None
return super().to_internal_value(data)


class NonStrictCharField(serializers.CharField):
""" Allow booleans to be turned into strings instead of error """
"""Allow booleans to be turned into strings instead of error"""

def to_internal_value(self, value):
if value is True:
return "True"
Expand All @@ -44,9 +60,21 @@ def to_internal_value(self, value):
class FilterFieldSerializer(serializers.ModelSerializer):
class Meta:
model = FilterField
fields = ('id', 'path', 'path_verbose', 'field', 'field_verbose',
'field_type', 'filter_type', 'filter_value', 'filter_value2',
'exclude', 'position', 'report', 'filter_delta')
fields = (
'id',
'path',
'path_verbose',
'field',
'field_verbose',
'field_type',
'filter_type',
'filter_value',
'filter_value2',
'exclude',
'position',
'report',
'filter_delta',
)
read_only_fields = ('id', 'field_type')

filter_value = NonStrictCharField(allow_blank=True)
Expand All @@ -65,15 +93,13 @@ class Meta:


class ReportSerializer(serializers.HyperlinkedModelSerializer):
root_model = serializers.PrimaryKeyRelatedField(
queryset=Report.allowed_models())
root_model = serializers.PrimaryKeyRelatedField(queryset=Report.allowed_models())
root_model_name = serializers.StringRelatedField(source='root_model')
user_created = UserSerializer(read_only=True)

class Meta:
model = Report
fields = ('id', 'name', 'modified', 'root_model', 'root_model_name',
'user_created')
fields = ('id', 'name', 'modified', 'root_model', 'root_model_name', 'user_created')


class ReportNestedSerializer(ReportSerializer):
Expand All @@ -85,10 +111,20 @@ class ReportNestedSerializer(ReportSerializer):
class Meta:
model = Report
fields = (
'id', 'name', 'description', 'modified', 'root_model',
'root_model_name', 'displayfield_set', 'distinct', 'user_created',
'user_modified', 'filterfield_set', 'report_file',
'report_file_creation')
'id',
'name',
'description',
'modified',
'root_model',
'root_model_name',
'displayfield_set',
'distinct',
'user_created',
'user_modified',
'filterfield_set',
'report_file',
'report_file_creation',
)
read_only_fields = ('report_file', 'report_file_creation')

def validate(self, data):
Expand All @@ -107,10 +143,8 @@ def update(self, instance, validated_data):

with transaction.atomic():
instance.name = validated_data.get('name', instance.name)
instance.description = validated_data.get(
'description', instance.description)
instance.distinct = validated_data.get(
'distinct', instance.distinct)
instance.description = validated_data.get('description', instance.description)
instance.distinct = validated_data.get('distinct', instance.distinct)
instance.modified = datetime.date.today()
instance.save()
instance.displayfield_set.all().delete()
Expand Down
5 changes: 2 additions & 3 deletions report_builder/api/tests.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from django.contrib.auth import get_user_model
from django.test import TestCase
from model_bakery import baker
from rest_framework.test import APIRequestFactory
from rest_framework.test import force_authenticate
from rest_framework.test import APIRequestFactory, force_authenticate

from .views import ContentTypeViewSet


User = get_user_model()


Expand All @@ -17,6 +17,5 @@ def test_content_viewset(self):
request = factory.get('/report_builder/api/contenttypes/')
force_authenticate(request, user=user)
response = view(request)
print(response.data)
self.assertEqual(response.status_code, 200)
self.assertTrue(response.data, "should return some content types")
Loading

0 comments on commit 58a8b53

Please sign in to comment.