diff --git a/docs/conf.py b/docs/conf.py
index 8ade9a1e..b29c95cb 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -17,9 +17,9 @@
# -- Project information -----------------------------------------------------
-project = 'Jandig ARte Help'
-copyright = '2019, pablodiegoss, rodrigocam, vjpixel, hvalois'
-author = 'pablodiegoss, rodrigocam, vjpixel, hvalois'
+project = "Jandig ARte Help"
+copyright = "2019, pablodiegoss, rodrigocam, vjpixel, hvalois"
+author = "pablodiegoss, rodrigocam, vjpixel, hvalois"
# -- General configuration ---------------------------------------------------
@@ -27,18 +27,17 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = [
-]
+extensions = []
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
-language = 'pt_BR'
+language = "pt_BR"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@@ -51,28 +50,29 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-html_theme = 'alabaster'
+html_theme = "alabaster"
# 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"]
html_theme_options = {
- 'logo': 'logo.png',
- 'github_user': 'memeLab',
- 'github_repo': 'Jandig',
- 'html_sidebars': {
- '**': [
- 'search.html',
- 'navigation.html',
- ]
+ "logo": "logo.png",
+ "github_user": "memeLab",
+ "github_repo": "Jandig",
+ "html_sidebars": {
+ "**": [
+ "search.html",
+ "navigation.html",
+ ]
},
- 'extra_nav_links': {
- 'Official Site': 'https://jandig.app',
- 'Github': 'https://github.com/memelab/Jandig'
+ "extra_nav_links": {
+ "Official Site": "https://jandig.app",
+ "Github": "https://github.com/memelab/Jandig",
},
}
+
def setup(app):
- app.add_css_file('reset.css')
\ No newline at end of file
+ app.add_css_file("reset.css")
diff --git a/etc/scripts/compilemessages.py b/etc/scripts/compilemessages.py
index 2af14779..0521787e 100644
--- a/etc/scripts/compilemessages.py
+++ b/etc/scripts/compilemessages.py
@@ -2,10 +2,10 @@
import glob
import os
-from subprocess import Popen, PIPE
+from subprocess import PIPE, Popen
-program = 'msgfmt'
-program_options = ['--check-format', '-f']
+program = "msgfmt"
+program_options = ["--check-format", "-f"]
def main():
@@ -14,26 +14,26 @@ def main():
django.core.management.commands.compilemessages
"""
# Walk entire tree, looking for locale directories
- basedirs = ['locale']
- for dirpath, dirnames, filenames in os.walk('.', topdown=True):
+ basedirs = ["locale"]
+ for dirpath, dirnames, filenames in os.walk(".", topdown=True):
for dirname in dirnames:
- if dirname == 'locale':
+ if dirname == "locale":
basedirs.append(os.path.join(dirpath, dirname))
basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs)))
# Build locale list
all_locales = []
for basedir in basedirs:
- locale_dirs = filter(os.path.isdir, glob.glob(f'{basedir}/*'))
+ locale_dirs = filter(os.path.isdir, glob.glob(f"{basedir}/*"))
all_locales.extend(map(os.path.basename, locale_dirs))
locales = set(all_locales)
for basedir in basedirs:
- dirs = [os.path.join(basedir, locale, 'LC_MESSAGES') for locale in locales]
+ dirs = [os.path.join(basedir, locale, "LC_MESSAGES") for locale in locales]
locations = []
for ldir in dirs:
for dirpath, dirnames, filenames in os.walk(ldir):
- locations.extend((dirpath, f) for f in filenames if f.endswith('.po'))
+ locations.extend((dirpath, f) for f in filenames if f.endswith(".po"))
compile_messages(locations)
@@ -42,21 +42,21 @@ def compile_messages(locations):
Locations is a list of tuples: [(directory, file), ...]
"""
for _, (dirpath, f) in enumerate(locations):
- print(f'processing file {f} in {dirpath}\n')
+ print(f"processing file {f} in {dirpath}\n")
# Program args
po_path = os.path.join(dirpath, f)
base_path = os.path.splitext(po_path)[0]
- extra_args = ['-o', base_path + '.mo', base_path + '.po']
+ extra_args = ["-o", base_path + ".mo", base_path + ".po"]
args = [program] + program_options + extra_args
# Execute command
__, errors, status = popen_wrapper(args)
if status:
if errors:
- msg = f'Execution of {program} failed: {errors}'
+ msg = f"Execution of {program} failed: {errors}"
else:
- msg = f'Execution of {program} failed'
+ msg = f"Execution of {program} failed"
raise RuntimeError(msg)
@@ -68,8 +68,8 @@ def popen_wrapper(args, os_err_exc_type=RuntimeError):
with Popen(args, shell=False, stdout=PIPE, stderr=PIPE, close_fds=True) as p:
output, errors = p.communicate()
return output, errors, p.returncode
- raise os_err_exc_type('Error executing')
+ raise os_err_exc_type("Error executing")
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/src/core/admin.py b/src/core/admin.py
index 2211979b..e5af7e08 100644
--- a/src/core/admin.py
+++ b/src/core/admin.py
@@ -1,6 +1,5 @@
-from django.contrib import admin
-
from core.models import Artwork, Exhibit, Marker, Object
+from django.contrib import admin
admin.site.register(Exhibit)
admin.site.register(Object)
diff --git a/src/core/models.py b/src/core/models.py
index 8f301cb3..4197da51 100644
--- a/src/core/models.py
+++ b/src/core/models.py
@@ -1,24 +1,22 @@
+import logging
import re
+from config.storage_backends import PublicMediaStorage
from django.core.files.base import ContentFile
from django.db import models
from django.db.models.signals import post_delete
from django.dispatch import receiver
from PIL import Image
from pymarker.core import generate_marker_from_image, generate_patt_from_image
-
-from config.storage_backends import PublicMediaStorage
from users.models import Profile
-import logging
log = logging.getLogger()
+
def create_patt(filename, original_filename):
filestorage = PublicMediaStorage()
with Image.open(filestorage.open(filename)) as image:
patt_str = generate_patt_from_image(image)
- # string_file = StringIO(patt_str.encode('UTF-8'))
- # string_file.name = original_filename
patt_file = filestorage.save(
"patts/" + original_filename + ".patt",
ContentFile(patt_str.encode("utf-8")),
@@ -32,12 +30,13 @@ def create_marker(filename, original_filename):
marker_image = generate_marker_from_image(image)
marker_image.name = original_filename
marker_image.__commited = False
- # marker = filestorage.save("markers/" + original_filename, marker_image)
return marker_image
class Marker(models.Model):
- owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING, related_name="markers")
+ owner = models.ForeignKey(
+ Profile, on_delete=models.DO_NOTHING, related_name="markers"
+ )
source = models.ImageField(upload_to="markers/")
uploaded_at = models.DateTimeField(auto_now=True)
author = models.CharField(max_length=60, blank=False)
@@ -45,23 +44,6 @@ class Marker(models.Model):
patt = models.FileField(upload_to="patts/")
def save(self, *args, **kwargs):
- # filestorage = PublicMediaStorage()
- # # Image Filename
- # original_filename = self.source.name
- # filename = filestorage.save(f"original_{original_filename}", self.source)
- # # Complete Image URL on storage
- # print("aaaaa"*30)
- # with Image.open(self.source) as image:
- # print(image)
- # print("aaaaa"*30)
- # # fileurl = filestorage.url(filename)
- # print(filename)
- # self.source = create_marker(filename, original_filename)
- # self.patt = create_patt(filename, original_filename)
- print("B" * 30)
- print(self.source)
- print(self.patt)
- print("B" * 30)
super().save(*args, **kwargs)
def __str__(self):
@@ -91,7 +73,9 @@ def in_use(self):
class Object(models.Model):
- owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING, related_name="ar_objects")
+ owner = models.ForeignKey(
+ Profile, on_delete=models.DO_NOTHING, related_name="ar_objects"
+ )
source = models.FileField(upload_to="objects/")
uploaded_at = models.DateTimeField(auto_now=True)
author = models.CharField(max_length=60, blank=False)
@@ -209,7 +193,9 @@ def yposition(self):
class Artwork(models.Model):
- author = models.ForeignKey(Profile, on_delete=models.DO_NOTHING, related_name="artworks")
+ author = models.ForeignKey(
+ Profile, on_delete=models.DO_NOTHING, related_name="artworks"
+ )
marker = models.ForeignKey(Marker, on_delete=models.DO_NOTHING)
augmented = models.ForeignKey(Object, on_delete=models.DO_NOTHING)
title = models.CharField(max_length=50, blank=False)
@@ -239,7 +225,9 @@ def remove_source_file(sender, instance, **kwargs):
class Exhibit(models.Model):
- owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING, related_name="exhibits")
+ owner = models.ForeignKey(
+ Profile, on_delete=models.DO_NOTHING, related_name="exhibits"
+ )
name = models.CharField(unique=True, max_length=50)
slug = models.CharField(unique=True, max_length=50)
artworks = models.ManyToManyField(Artwork, related_name="exhibits")
diff --git a/src/core/serializers/artworks.py b/src/core/serializers/artworks.py
index 04751a7d..30e3627d 100644
--- a/src/core/serializers/artworks.py
+++ b/src/core/serializers/artworks.py
@@ -1,6 +1,5 @@
-from rest_framework.serializers import ModelSerializer
-
from core.models import Artwork
+from rest_framework.serializers import ModelSerializer
class ArtworkSerializer(ModelSerializer):
diff --git a/src/core/serializers/exhibits.py b/src/core/serializers/exhibits.py
index 502e7272..5981d01c 100644
--- a/src/core/serializers/exhibits.py
+++ b/src/core/serializers/exhibits.py
@@ -1,6 +1,5 @@
-from rest_framework.serializers import ModelSerializer
-
from core.models import Exhibit
+from rest_framework.serializers import ModelSerializer
class ExhibitSerializer(ModelSerializer):
diff --git a/src/core/serializers/markers.py b/src/core/serializers/markers.py
index 9b0ac3ae..7dd53f8a 100644
--- a/src/core/serializers/markers.py
+++ b/src/core/serializers/markers.py
@@ -1,6 +1,5 @@
-from rest_framework.serializers import ModelSerializer
-
from core.models import Marker
+from rest_framework.serializers import ModelSerializer
class MarkerSerializer(ModelSerializer):
diff --git a/src/core/serializers/objects.py b/src/core/serializers/objects.py
index 38f7edd4..0c789f25 100644
--- a/src/core/serializers/objects.py
+++ b/src/core/serializers/objects.py
@@ -1,6 +1,5 @@
-from rest_framework.serializers import ModelSerializer
-
from core.models import Object
+from rest_framework.serializers import ModelSerializer
class ObjectSerializer(ModelSerializer):
diff --git a/src/core/tests/test_artworks_api.py b/src/core/tests/test_artworks_api.py
index f1df0650..80e42996 100644
--- a/src/core/tests/test_artworks_api.py
+++ b/src/core/tests/test_artworks_api.py
@@ -1,10 +1,9 @@
"""Test using the artwork API for Jandig Artwork"""
+from core.models import Artwork, Marker, Object
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
-
-from core.models import Artwork, Marker, Object
from users.models import User
fake_file = SimpleUploadedFile("fake_file.png", b"these are the file contents!")
@@ -27,7 +26,9 @@ def test_url(self):
def test_api_artworks_lists_one_artwork(self):
marker = Marker.objects.create(owner=self.profile, source=fake_file)
obj = Object.objects.create(owner=self.profile, source=fake_file)
- artwork = Artwork.objects.create(author=self.profile, augmented=obj, marker=marker)
+ artwork = Artwork.objects.create(
+ author=self.profile, augmented=obj, marker=marker
+ )
self.assertEqual(artwork.author, self.profile)
response = self.client.get("/api/v1/artworks/")
self.assertEqual(response.status_code, 200)
@@ -44,7 +45,9 @@ def test_api_artwork_lists_multiple_artworks(self):
def test_retrieve_artwork(self):
marker = Marker.objects.create(owner=self.profile, source=fake_file)
obj = Object.objects.create(owner=self.profile, source=fake_file)
- artwork = Artwork.objects.create(author=self.profile, augmented=obj, marker=marker) # noqa F841
+ artwork = Artwork.objects.create(
+ author=self.profile, augmented=obj, marker=marker
+ ) # noqa F841
self.assertEqual(artwork.author, self.profile)
response = self.client.get("/api/v1/artworks/1/")
diff --git a/src/core/tests/test_exhibits_api.py b/src/core/tests/test_exhibits_api.py
index 66365b98..e81e9d38 100644
--- a/src/core/tests/test_exhibits_api.py
+++ b/src/core/tests/test_exhibits_api.py
@@ -1,10 +1,9 @@
"""Test using the exhibit API for Jandig Exhibit"""
+from core.models import Artwork, Exhibit, Marker, Object
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
-
-from core.models import Artwork, Exhibit, Marker, Object
from users.models import User
fake_file = SimpleUploadedFile("fake_file.png", b"these are the file contents!")
@@ -27,7 +26,9 @@ def test_url(self):
def test_api_exhibits_lists_one_exhibit(self):
marker = Marker.objects.create(owner=self.profile, source=fake_file)
obj = Object.objects.create(owner=self.profile, source=fake_file)
- artwork = Artwork.objects.create(author=self.profile, augmented=obj, marker=marker)
+ artwork = Artwork.objects.create(
+ author=self.profile, augmented=obj, marker=marker
+ )
exhibit = Exhibit.objects.create(owner=self.profile, name="test")
exhibit.artworks.add(artwork)
response = self.client.get("/api/v1/artworks/")
@@ -37,15 +38,21 @@ def test_api_exhibit_lists_multiple_exhibits(self):
for i in range(0, settings.PAGE_SIZE + 1):
marker = Marker.objects.create(owner=self.profile, source=fake_file)
obj = Object.objects.create(owner=self.profile, source=fake_file)
- artwork = Artwork.objects.create(author=self.profile, augmented=obj, marker=marker) # noqa F841
- exhibit = Exhibit.objects.create(owner=self.profile, name=f"name_{i}", slug=f"slug_{i}") # noqa F841
+ artwork = Artwork.objects.create(
+ author=self.profile, augmented=obj, marker=marker
+ ) # noqa F841
+ exhibit = Exhibit.objects.create(
+ owner=self.profile, name=f"name_{i}", slug=f"slug_{i}"
+ ) # noqa F841
response = self.client.get("/api/v1/exhibits/")
self.assertEqual(response.status_code, 200)
def test_retrieve_exhibit(self):
marker = Marker.objects.create(owner=self.profile, source=fake_file)
obj = Object.objects.create(owner=self.profile, source=fake_file)
- artwork = Artwork.objects.create(author=self.profile, augmented=obj, marker=marker)
+ artwork = Artwork.objects.create(
+ author=self.profile, augmented=obj, marker=marker
+ )
exhibit = Exhibit.objects.create(owner=self.profile, name="test")
exhibit.artworks.add(artwork)
response = self.client.get("/api/v1/exhibits/1/")
diff --git a/src/core/tests/test_markers_api.py b/src/core/tests/test_markers_api.py
index 3ce10ad5..ab68ac22 100644
--- a/src/core/tests/test_markers_api.py
+++ b/src/core/tests/test_markers_api.py
@@ -1,11 +1,10 @@
"""Test using the marker API for Jandig Markers"""
+from core.models import Marker
+from core.serializers.markers import MarkerSerializer
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
-
-from core.models import Marker
-from core.serializers.markers import MarkerSerializer
from users.models import User
fake_file = SimpleUploadedFile("fake_file.png", b"these are the file contents!")
diff --git a/src/core/tests/test_objects_api.py b/src/core/tests/test_objects_api.py
index d084ad78..621cc942 100644
--- a/src/core/tests/test_objects_api.py
+++ b/src/core/tests/test_objects_api.py
@@ -1,11 +1,10 @@
"""Test using the object API for Jandig Objects"""
+from core.models import Object
+from core.serializers.objects import ObjectSerializer
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
-
-from core.models import Object
-from core.serializers.objects import ObjectSerializer
from users.models import User
fake_file = SimpleUploadedFile("fake_file.png", b"these are the file contents!")
diff --git a/src/core/views/artworks.py b/src/core/views/artworks.py
index eaaea233..2927f460 100644
--- a/src/core/views/artworks.py
+++ b/src/core/views/artworks.py
@@ -1,8 +1,7 @@
-from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
-from rest_framework.viewsets import GenericViewSet
-
from core.models import Artwork
from core.serializers.artworks import ArtworkSerializer
+from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
+from rest_framework.viewsets import GenericViewSet
class ArtworkViewset(ListModelMixin, RetrieveModelMixin, GenericViewSet):
diff --git a/src/core/views/exhibits.py b/src/core/views/exhibits.py
index e3a2fe46..e65479d9 100644
--- a/src/core/views/exhibits.py
+++ b/src/core/views/exhibits.py
@@ -1,8 +1,7 @@
-from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
-from rest_framework.viewsets import GenericViewSet
-
from core.models import Exhibit
from core.serializers.exhibits import ExhibitSerializer
+from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
+from rest_framework.viewsets import GenericViewSet
class ExhibitViewset(ListModelMixin, RetrieveModelMixin, GenericViewSet):
diff --git a/src/core/views/markers.py b/src/core/views/markers.py
index bd185f5a..95192e64 100644
--- a/src/core/views/markers.py
+++ b/src/core/views/markers.py
@@ -1,8 +1,7 @@
-from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
-from rest_framework.viewsets import GenericViewSet
-
from core.models import Marker
from core.serializers.markers import MarkerSerializer
+from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
+from rest_framework.viewsets import GenericViewSet
class MarkerViewset(ListModelMixin, RetrieveModelMixin, GenericViewSet):
diff --git a/src/core/views/objects.py b/src/core/views/objects.py
index e7a01f61..3e29e5be 100644
--- a/src/core/views/objects.py
+++ b/src/core/views/objects.py
@@ -1,8 +1,7 @@
-from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
-from rest_framework.viewsets import GenericViewSet
-
from core.models import Object
from core.serializers.objects import ObjectSerializer
+from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
+from rest_framework.viewsets import GenericViewSet
class ObjectViewset(ListModelMixin, RetrieveModelMixin, GenericViewSet):
diff --git a/src/core/views/static_views.py b/src/core/views/static_views.py
index c7016f94..4a8fbf81 100644
--- a/src/core/views/static_views.py
+++ b/src/core/views/static_views.py
@@ -1,7 +1,8 @@
-from django.http import JsonResponse, HttpResponse
+from django.http import HttpResponse, JsonResponse
from django.shortcuts import redirect, render
from django.templatetags.static import static
+
def home(request):
return render(request, "users/profile.jinja2", {})
@@ -35,4 +36,4 @@ def robots_txt(request):
"User-Agent: *",
"Disallow: ",
]
- return HttpResponse("\n".join(lines), content_type="text/plain")
\ No newline at end of file
+ return HttpResponse("\n".join(lines), content_type="text/plain")
diff --git a/src/manage.py b/src/manage.py
index 41464304..312127d5 100755
--- a/src/manage.py
+++ b/src/manage.py
@@ -7,5 +7,9 @@
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
- raise ImportError("Couldn't import Django. Are you sure it's installed and " "available on your PYTHONPATH environment variable? Did you " "forget to activate a virtual environment?") from exc
+ raise ImportError(
+ "Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?"
+ ) from exc
execute_from_command_line(sys.argv)
diff --git a/src/tests/home_tests.py b/src/tests/home_tests.py
index a1cc097e..6e6d5d6f 100644
--- a/src/tests/home_tests.py
+++ b/src/tests/home_tests.py
@@ -1,6 +1,8 @@
import re
+
from playwright.sync_api import Page, expect
+
def test_home_loads_in_english(page: Page):
page.goto("http://localhost:8000/")
@@ -19,4 +21,4 @@ def test_changing_language_to_portuguese_and_back_to_english(page: Page) -> None
page.get_by_label("en-us").check()
page.get_by_role("button", name="Ok").click()
expect(page).to_have_url("http://localhost:8000/")
- expect(page.get_by_role("heading")).to_have_text("Welcome to Jandig")
\ No newline at end of file
+ expect(page.get_by_role("heading")).to_have_text("Welcome to Jandig")
diff --git a/src/users/admin.py b/src/users/admin.py
index 64b5c99c..189d1f8e 100644
--- a/src/users/admin.py
+++ b/src/users/admin.py
@@ -1,22 +1,25 @@
from typing import Any
+
from django.contrib import admin
+from django.contrib.admin.filters import ListFilter
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
+from django.db.models import Count, Q
from django.db.models.query import QuerySet
from django.http import HttpRequest
-from django.db.models import Q, Count
from django.urls import reverse
from django.utils.html import format_html
-from django.contrib import admin
from users.models import Profile
-from django.contrib.admin.filters import ListFilter
+
admin.site.unregister(User)
+
class NoArtFilter(admin.SimpleListFilter):
title = "Art Qtdy"
# Parameter for the filter that will be used in the URL query.
parameter_name = "art_qtd"
+
def lookups(self, request, model_admin):
return [
("no_artwork", "Zero Artworks"),
@@ -40,37 +43,58 @@ def queryset(self, request, queryset):
if "no_exhibits" in query:
conditions &= Q(_exhibits_count=0)
if "no_art" in query:
- return queryset.filter(Q(_artworks_count=0)&Q(_ar_objects_count=0)&Q(_exhibits_count=0)&Q(_markers_count=0))
-
+ return queryset.filter(
+ Q(_artworks_count=0)
+ & Q(_ar_objects_count=0)
+ & Q(_exhibits_count=0)
+ & Q(_markers_count=0)
+ )
+
# Apply the filter
filtered_queryset = queryset.filter(conditions)
return filtered_queryset
+
@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
- list_display=["id", "user_link","artworks_count","markers_count","ar_objects_count","exhibits_count", "created", "last_login"]
- ordering=["-id"]
+ list_display = [
+ "id",
+ "user_link",
+ "artworks_count",
+ "markers_count",
+ "ar_objects_count",
+ "exhibits_count",
+ "created",
+ "last_login",
+ ]
+ ordering = ["-id"]
list_filter = [NoArtFilter]
+
def get_queryset(self, request):
- queryset = super().get_queryset(request).select_related("user").prefetch_related("artworks", "markers", "exhibits", "ar_objects")
+ queryset = (
+ super()
+ .get_queryset(request)
+ .select_related("user")
+ .prefetch_related("artworks", "markers", "exhibits", "ar_objects")
+ )
queryset = queryset.annotate(
- _markers_count = Count("markers", distinct=True),
- _artworks_count = Count("artworks", distinct=True),
- _ar_objects_count = Count("ar_objects", distinct=True),
- _exhibits_count = Count("exhibits", distinct=True)
+ _markers_count=Count("markers", distinct=True),
+ _artworks_count=Count("artworks", distinct=True),
+ _ar_objects_count=Count("ar_objects", distinct=True),
+ _exhibits_count=Count("exhibits", distinct=True),
)
return queryset
-
+
def username(self, obj):
return obj.user.username
- def created(self,obj):
+ def created(self, obj):
return obj.user.date_joined
- def last_login(self,obj):
+ def last_login(self, obj):
return obj.user.last_login
- def user_link(self,obj):
+ def user_link(self, obj):
"""Link to related User"""
link = reverse("admin:index") + "auth/user/?id=" + str(obj.user.id)
return format_html('{}', link, obj.user.username)
@@ -80,29 +104,36 @@ def artworks_count(self, obj):
def markers_count(self, obj):
return obj._markers_count
-
+
def ar_objects_count(self, obj):
return obj._ar_objects_count
-
+
def exhibits_count(self, obj):
return obj._exhibits_count
artworks_count.admin_order_field = "_artworks_count"
- markers_count.admin_order_field= "_markers_count"
- ar_objects_count.admin_order_field="_ar_objects_count"
- exhibits_count.admin_order_field="_exhibits_count"
+ markers_count.admin_order_field = "_markers_count"
+ ar_objects_count.admin_order_field = "_ar_objects_count"
+ exhibits_count.admin_order_field = "_exhibits_count"
@admin.register(User)
class JandigUserAdmin(UserAdmin):
- list_display = ("username", "email","profile_link", "last_login", "date_joined", "is_staff")
+ list_display = (
+ "username",
+ "email",
+ "profile_link",
+ "last_login",
+ "date_joined",
+ "is_staff",
+ )
list_filter = ("is_staff", "is_superuser", "is_active", "groups")
+
def get_queryset(self, request: HttpRequest) -> QuerySet[Any]:
queryset = super().get_queryset(request).select_related("profile")
return queryset
-
- def profile_link(self,obj):
+ def profile_link(self, obj):
"""Link to related Profile"""
link = reverse("admin:index") + "users/profile/?id=" + str(obj.profile.id)
return format_html('{}', link, obj.username)
diff --git a/src/users/factory.py b/src/users/factory.py
index fc89688a..382c92ab 100644
--- a/src/users/factory.py
+++ b/src/users/factory.py
@@ -1,8 +1,7 @@
+from core.models import Object
from django.contrib.auth.models import User
from factory.django import DjangoModelFactory
-from core.models import Object
-
class UserFactory(DjangoModelFactory):
username = "Testador"
diff --git a/src/users/forms.py b/src/users/forms.py
index 7e321b84..6a8cb328 100644
--- a/src/users/forms.py
+++ b/src/users/forms.py
@@ -2,6 +2,7 @@
import re
from io import BytesIO
+from core.models import Marker, Object
from django import forms
from django.contrib.auth import authenticate, get_user_model
from django.contrib.auth.forms import AuthenticationForm
@@ -13,8 +14,6 @@
from PIL import Image
from pymarker.core import generate_marker_from_image, generate_patt_from_image
-from core.models import Marker, Object
-
from .choices import COUNTRY_CHOICES
log = logging.getLogger("ej")
@@ -52,7 +51,10 @@ class Meta:
def clean_email(self):
email = self.cleaned_data.get("email")
username = self.cleaned_data.get("username")
- if email and User.objects.filter(email=email).exclude(username=username).exists():
+ if (
+ email
+ and User.objects.filter(email=email).exclude(username=username).exists()
+ ):
raise forms.ValidationError(_("E-mail taken"))
return email
@@ -63,7 +65,9 @@ def __init__(self, *args, **kwargs):
super(PasswordChangeForm, self).__init__(*args, **kwargs)
self.fields["old_password"].widget.attrs["placeholder"] = _("Old Password")
self.fields["new_password1"].widget.attrs["placeholder"] = _("New Password")
- self.fields["new_password2"].widget.attrs["placeholder"] = _("New Password Again")
+ self.fields["new_password2"].widget.attrs["placeholder"] = _(
+ "New Password Again"
+ )
class ProfileForm(forms.ModelForm):
@@ -110,13 +114,23 @@ def __init__(self, *args, **kwargs):
def clean_username(self):
username = self.cleaned_data.get("username")
- if username and User.objects.filter(username=username).exclude(username=self.instance.user.username).exists():
+ if (
+ username
+ and User.objects.filter(username=username)
+ .exclude(username=self.instance.user.username)
+ .exists()
+ ):
raise forms.ValidationError(_("Username already in use"))
return username
def clean_email(self):
email = self.cleaned_data.get("email")
- if email and User.objects.filter(email=email).exclude(username=self.instance.user.username).exists():
+ if (
+ email
+ and User.objects.filter(email=email)
+ .exclude(username=self.instance.user.username)
+ .exists()
+ ):
raise forms.ValidationError(_("Email address must be unique"))
return email
@@ -184,7 +198,9 @@ def __init__(self, *args, **kwargs):
log.warning(self.fields)
self.fields["source"].widget.attrs["placeholder"] = _("browse file")
self.fields["source"].widget.attrs["accept"] = "image/png, image/jpg"
- self.fields["author"].widget.attrs["placeholder"] = _("declare different author name")
+ self.fields["author"].widget.attrs["placeholder"] = _(
+ "declare different author name"
+ )
self.fields["title"].widget.attrs["placeholder"] = _("Marker's title")
class Meta:
@@ -221,7 +237,9 @@ def __init__(self, *args, **kwargs):
self.fields["source"].widget.attrs["placeholder"] = _("browse file")
self.fields["source"].widget.attrs["accept"] = "image/*, .mp4, .webm"
- self.fields["author"].widget.attrs["placeholder"] = _("declare different author name")
+ self.fields["author"].widget.attrs["placeholder"] = _(
+ "declare different author name"
+ )
self.fields["scale"].widget = HiddenInput()
self.fields["rotation"].widget = HiddenInput()
self.fields["position"].widget = HiddenInput()
@@ -254,10 +272,16 @@ class ArtworkForm(forms.Form):
def __init__(self, *args, **kwargs):
super(ArtworkForm, self).__init__(*args, **kwargs)
- self.fields["marker_author"].widget.attrs["placeholder"] = _("declare different author name")
- self.fields["augmented_author"].widget.attrs["placeholder"] = _("declare different author name")
+ self.fields["marker_author"].widget.attrs["placeholder"] = _(
+ "declare different author name"
+ )
+ self.fields["augmented_author"].widget.attrs["placeholder"] = _(
+ "declare different author name"
+ )
self.fields["title"].widget.attrs["placeholder"] = _("Artwork title")
- self.fields["description"].widget.attrs["placeholder"] = _("Artwork description")
+ self.fields["description"].widget.attrs["placeholder"] = _(
+ "Artwork description"
+ )
class ExhibitForm(forms.Form):
@@ -271,11 +295,15 @@ class ExhibitForm(forms.Form):
def clean_slug(self):
data = self.cleaned_data["slug"]
if not re.match("^[a-zA-Z0-9_]*$", data):
- raise forms.ValidationError(_("Url can't contain spaces or special characters"))
+ raise forms.ValidationError(
+ _("Url can't contain spaces or special characters")
+ )
return data
def __init__(self, *args, **kwargs):
super(ExhibitForm, self).__init__(*args, **kwargs)
self.fields["name"].widget.attrs["placeholder"] = _("Exhibit Title")
- self.fields["slug"].widget.attrs["placeholder"] = _("Complete with your Exhibit URL here")
+ self.fields["slug"].widget.attrs["placeholder"] = _(
+ "Complete with your Exhibit URL here"
+ )
diff --git a/src/users/tests/test_users.py b/src/users/tests/test_users.py
index 0bb37a02..41acf9bc 100644
--- a/src/users/tests/test_users.py
+++ b/src/users/tests/test_users.py
@@ -1,7 +1,6 @@
from unittest import mock
from django.test import RequestFactory, TestCase
-
from users.factory import UserFactory
from users.services.email_service import EmailService
from users.services.encrypt_service import EncryptService
@@ -35,20 +34,26 @@ def test_recover_password_invalid_email(self, *args, **kwargs):
self.assertEqual(response.url, "/users/invalid-recovering-email")
def test_recover_password_invalid_username(self, *args, **kwargs):
- request = self.client_test.post("/recover/", {"username_or_email": "testadorinvalid"}, follow=True)
+ request = self.client_test.post(
+ "/recover/", {"username_or_email": "testadorinvalid"}, follow=True
+ )
response = recover_password(request)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/users/invalid-recovering-email")
def test_recover_password_valid_email(self, *args, **kwargs):
- request = self.client_test.post("/recover/", {"username_or_email": "testador@memelab.com"}, follow=True)
+ request = self.client_test.post(
+ "/recover/", {"username_or_email": "testador@memelab.com"}, follow=True
+ )
UserFactory()
response = recover_password(request)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/users/recover-code/")
def test_recover_password_valid_username(self, *args, **kwargs):
- request = self.client_test.post("/recover/", {"username_or_email": "Testador"}, follow=True)
+ request = self.client_test.post(
+ "/recover/", {"username_or_email": "Testador"}, follow=True
+ )
UserFactory()
response = recover_password(request)
self.assertEqual(response.status_code, 302)
diff --git a/src/users/views.py b/src/users/views.py
index 76b5bdb0..1c5c89ea 100644
--- a/src/users/views.py
+++ b/src/users/views.py
@@ -1,6 +1,7 @@
import json
import logging
+from core.models import Artwork, Exhibit, Marker, Object
from django.contrib.auth import (
authenticate,
get_user_model,
@@ -14,8 +15,6 @@
from django.views.decorators.cache import cache_page
from django.views.decorators.http import require_http_methods
-from core.models import Artwork, Exhibit, Marker, Object
-
from .forms import (
ArtworkForm,
ExhibitForm,
@@ -61,9 +60,13 @@ def recover_password(request):
recover_password_form = RecoverPasswordForm(request.POST)
if recover_password_form.is_valid():
- username_or_email = recover_password_form.cleaned_data.get("username_or_email")
+ username_or_email = recover_password_form.cleaned_data.get(
+ "username_or_email"
+ )
user_service = UserService()
- username_or_email_is_valid = user_service.check_if_username_or_email_exist(username_or_email)
+ username_or_email_is_valid = user_service.check_if_username_or_email_exist(
+ username_or_email
+ )
if not username_or_email_is_valid:
return redirect("invalid_recovering_email_or_username")
@@ -72,14 +75,18 @@ def recover_password(request):
global global_verification_code
encrypt_service = EncryptService()
- global_verification_code = encrypt_service.generate_verification_code(global_recovering_email)
+ global_verification_code = encrypt_service.generate_verification_code(
+ global_recovering_email
+ )
build_message_and_send_to_user(global_recovering_email)
return redirect("recover-code")
recover_password_form = RecoverPasswordForm()
- return render(request, "users/recover-password.jinja2", {"form": recover_password_form})
+ return render(
+ request, "users/recover-password.jinja2", {"form": recover_password_form}
+ )
def build_message_and_send_to_user(email):
@@ -144,7 +151,9 @@ def profile(request):
if not user:
user = request.user
- profile = Profile.objects.prefetch_related("exhibits", "markers", "ar_objects", "artworks").get(user=user)
+ profile = Profile.objects.prefetch_related(
+ "exhibits", "markers", "ar_objects", "artworks"
+ ).get(user=user)
exhibits = profile.exhibits.all()
markers = profile.markers.all()
diff --git a/tasks.py b/tasks.py
index 4194aa1f..75d12c76 100644
--- a/tasks.py
+++ b/tasks.py
@@ -4,24 +4,24 @@
python = sys.executable
directory = os.path.dirname(__file__)
-sys.path.append('jandig')
+sys.path.append("jandig")
#
# Call python manage.py in a more robust way
#
def robust_manage(ctx, cmd, env=None, **kwargs):
- kwargs = {k.replace('_', '-'): v for k, v in kwargs.items() if v is not False}
- opts = ' '.join(f'--{k} {"" if v is True else v}' for k, v in kwargs.items())
- cmd = f'{python} ./src/manage.py {cmd} {opts}'
+ kwargs = {k.replace("_", "-"): v for k, v in kwargs.items() if v is not False}
+ opts = " ".join(f'--{k} {"" if v is True else v}' for k, v in kwargs.items())
+ cmd = f"{python} ./src/manage.py {cmd} {opts}"
env = {**os.environ, **(env or {})}
path = env.get("PYTHONPATH", ":".join(sys.path))
- env.setdefault('PYTHONPATH', f'src:{path}')
+ env.setdefault("PYTHONPATH", f"src:{path}")
print(cmd)
ctx.run(cmd, pty=True, env=env)
def manage(ctx, cmd):
- cmd = f'python3 ./src/manage.py {cmd}'
+ cmd = f"python3 ./src/manage.py {cmd}"
ctx.run(cmd, pty=True, env=os.environ)
@@ -31,7 +31,9 @@ def run(ctx, ssl=False, gunicorn=False):
Run development server
"""
if gunicorn:
- ctx.run('cd src && gunicorn --reload --worker-connections=10000 --workers=4 --log-level debug --bind 0.0.0.0:8000 config.wsgi')
+ ctx.run(
+ "cd src && gunicorn --reload --worker-connections=10000 --workers=4 --log-level debug --bind 0.0.0.0:8000 config.wsgi"
+ )
else:
manage(ctx, "runserver 0.0.0.0:8000")
@@ -60,34 +62,36 @@ def collect(ctx):
# Translations
#
@task
-def i18n(ctx, compile=False, edit=False, lang='pt_BR', keep_pot=False):
+def i18n(ctx, compile=False, edit=False, lang="pt_BR", keep_pot=False):
"""
Extract messages for translation.
"""
if edit:
- ctx.run(f'poedit locale/{lang}/LC_MESSAGES/django.po')
+ ctx.run(f"poedit locale/{lang}/LC_MESSAGES/django.po")
elif compile:
- ctx.run(f'{python} etc/scripts/compilemessages.py')
+ ctx.run(f"{python} etc/scripts/compilemessages.py")
else:
- print('Collecting messages')
- robust_manage(ctx, 'makemessages', keep_pot=True, locale=lang)
+ print("Collecting messages")
+ robust_manage(ctx, "makemessages", keep_pot=True, locale=lang)
- print('Extract Jinja translations')
- ctx.run('pybabel extract -F ./etc/babel.cfg -o ./locale/jinja2.pot .')
+ print("Extract Jinja translations")
+ ctx.run("pybabel extract -F ./etc/babel.cfg -o ./locale/jinja2.pot .")
- print('Join Django + Jinja translation files')
- ctx.run('msgcat ./locale/django.pot ./locale/jinja2.pot --use-first -o ./locale/join.pot',
- pty=True)
- ctx.run(r'''sed -i '/"Language: \\n"/d' ./locale/join.pot''', pty=True)
+ print("Join Django + Jinja translation files")
+ ctx.run(
+ "msgcat ./locale/django.pot ./locale/jinja2.pot --use-first -o ./locale/join.pot",
+ pty=True,
+ )
+ ctx.run(r"""sed -i '/"Language: \\n"/d' ./locale/join.pot""", pty=True)
- print(f'Update locale {lang} with Jinja2 messages')
- ctx.run(f'msgmerge ./locale/{lang}/LC_MESSAGES/django.po ./locale/join.pot -U')
+ print(f"Update locale {lang} with Jinja2 messages")
+ ctx.run(f"msgmerge ./locale/{lang}/LC_MESSAGES/django.po ./locale/join.pot -U")
if not keep_pot:
- print('Cleaning up')
- ctx.run('rm ./locale/*.pot')
+ print("Cleaning up")
+ ctx.run("rm ./locale/*.pot")
@task
def docs(ctx):
- ctx.run('sphinx-build docs/ build/')
+ ctx.run("sphinx-build docs/ build/")