verejny kontaktnicek #71

Merged
ticvac merged 10 commits from kontaktnicek_pro_vsecny into master 2024-11-12 21:15:25 +01:00
7 changed files with 54 additions and 26 deletions
Showing only changes of commit 2dbbb588d0 - Show all commits

10
Dockerfile Normal file
View file

@ -0,0 +1,10 @@
FROM python:3.11.10-bookworm
WORKDIR /usr/src/app
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]

12
docker-compose.yaml Normal file
View file

@ -0,0 +1,12 @@
version: '3'
services:
django_app:
build: .
volumes:
- this_vol:/usr/src/app/
ports:
- 8000:8000
volumes:
this_vol:

View file

@ -342,6 +342,7 @@ SEMINAR_KONFERY_DIR = os.path.join('konfery')
KOREKTURY_PDF_DIR = os.path.join('korektury', 'pdf') KOREKTURY_PDF_DIR = os.path.join('korektury', 'pdf')
KOREKTURY_IMG_DIR = os.path.join('korektury', 'img') KOREKTURY_IMG_DIR = os.path.join('korektury', 'img')
CISLO_IMG_DIR = os.path.join('cislo', 'img') CISLO_IMG_DIR = os.path.join('cislo', 'img')
SOUSTREDENI_KONTAKTNICKY_DIR = os.path.join('soustredeni', 'kontaktnicky')

View file

@ -1,8 +1,8 @@
-c constraints.txt # -c constraints.txt
setuptools # django-polymorphic má rozbité dependencies setuptools # django-polymorphic má rozbité dependencies
# basic libs # basic libs
psycopg2 # PostgreSQL adaptér # psycopg2 # PostgreSQL adaptér
ipython # Interaktivní shell ipython # Interaktivní shell
Unidecode # Přepisuje unicode do ASCII (např. soubory nebo e-maily) Unidecode # Přepisuje unicode do ASCII (např. soubory nebo e-maily)
Pillow Pillow

View file

@ -18,9 +18,11 @@ from django.utils import timezone
def generate_filename_kontaktnicek(self, filename): def generate_filename_kontaktnicek(self, filename):
# generate random string # generate random string
length = 32 length = 32
fname = "kontaktnicky/" + timezone.now().strftime('%Y-%m-%d-%H_%M') file_type = filename.split('.')[-1]
fname = "kontaktnicky/" + timezone.now().strftime('%Y-%m-%d-%H_%M') + ""

Tohle nezachvá příponu, což je spíš bug – když se dívám na soubory na Gimlim, tak chci vědět, co jsou zač.

Tohle nezachvá příponu, což je spíš bug – když se dívám na soubory na Gimlim, tak chci vědět, co jsou zač.
fname += ''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(length)) fname += ''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(length))

Prosím ne KOREKTURY_PDF_DIR!!

Prosím ne `KOREKTURY_PDF_DIR`!!

Also: možná je snazší a bezpečnější použít pathlib než os.path.join

Also: možná je snazší a bezpečnější použít `pathlib` než `os.path.join`…
return os.path.join(settings.KOREKTURY_PDF_DIR, fname) fname += '.' + file_type
return os.path.join(settings.SOUSTREDENI_KONTAKTNICKY_DIR, fname)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -76,8 +78,8 @@ class Soustredeni(SeminarModelBase):
exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False, exportovat = models.BooleanField('export do AESOPa', db_column='exportovat', default=False,
help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)') help_text='Exportuje se jen podle tohoto flagu (ne veřejnosti)')

Nemá to být null=True? (Ale já tomu nerozumím…)

Nemá to být `null=True`? (Ale já tomu nerozumím…)
kontaktnicek_vcf = models.FileField('kontaktníček vcf', upload_to=generate_filename_kontaktnicek, blank=True,) kontaktnicek_vcf = models.FileField('kontaktníček vcf', upload_to=generate_filename_kontaktnicek, blank=True, null=True)
kontaktnicek_pdf = models.FileField('kontaktníček pdf', upload_to=generate_filename_kontaktnicek, blank=True,) kontaktnicek_pdf = models.FileField('kontaktníček pdf', upload_to=generate_filename_kontaktnicek, blank=True, null=True)
def __str__(self): def __str__(self):
return '{} ({})'.format(self.misto, self.datum_zacatku) return '{} ({})'.format(self.misto, self.datum_zacatku)

View file

@ -47,12 +47,12 @@ urlpatterns = [
path( path(
'kontaktnicek_pdf', 'kontaktnicek_pdf',
views.soustredeniKontaktnicekPdfView, views.soustredeniKontaktnicekPdfView,
name='soustredeni_kontaktnicek' name='soustredeni_kontaktnicek_pdf'
), ),
path( path(
'kontaktnicek_vcf', 'kontaktnicek_vcf',
views.soustredeniKontaktnicekVcfView, views.soustredeniKontaktnicekVcfView,
name='soustredeni_kontaktnicek' name='soustredeni_kontaktnicek_vcf'

Stejný name pro obě URL nevypadá moc správně :-(

Stejný `name` pro obě URL nevypadá moc správně :-(
), ),
zelvuska marked this conversation as resolved
Review

Tady je nějaké divné odsazení…

Tady je nějaké divné odsazení…
path( path(
'fotogalerie/', 'fotogalerie/',

View file

@ -3,6 +3,7 @@ from django.http import HttpResponse
from django.views import generic from django.views import generic
from django.contrib.staticfiles.finders import find from django.contrib.staticfiles.finders import find
from django.http import Http404 from django.http import Http404
from django.core.exceptions import PermissionDenied
import csv import csv
import tempfile import tempfile
@ -108,7 +109,7 @@ class SoustredeniAbstraktyView(generic.DetailView):
template_name = 'soustredeni/export_do_abstraktu.html' template_name = 'soustredeni/export_do_abstraktu.html'
pk_url_kwarg = 'soustredeni' # v url bude <int:soustredeni> místo defaultně požadovaného <int:pk> pk_url_kwarg = 'soustredeni' # v url bude <int:soustredeni> místo defaultně požadovaného <int:pk>
zelvuska marked this conversation as resolved Outdated

Diakritika maybe?

Diakritika maybe?
# kontaktnicek # Kontaktníčky
def soustredeniKontaktnicekPdfView(request, soustredeni): def soustredeniKontaktnicekPdfView(request, soustredeni):
return soustredeniKontaktnicekView(request, soustredeni, "pdf") return soustredeniKontaktnicekView(request, soustredeni, "pdf")
@ -117,22 +118,24 @@ def soustredeniKontaktnicekVcfView(request, soustredeni):
def soustredeniKontaktnicekView(request, soustredeni, typ): def soustredeniKontaktnicekView(request, soustredeni, typ):
soustredeni = get_object_or_404(Soustredeni, id=soustredeni) soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
# nebyl jsi tam, nebo nejsi org
if (not request.user in [u.osoba.user for u in soustredeni.ucastnici.all()]): if (not request.user in [u.osoba.user for u in soustredeni.ucastnici.all()]) and not request.user.je_org:

Asi bych napsal popisnější hlášku, vynechal bych tu část z orgem, a naopak bych tam připsal, že nejsi přihlášený (to se stane asi častěji než že bych se dostal na špatný kontaktníček).

Také si nejsem jistý, jestli HttpResponse je to správné. (Jakože vrátí to něco, co moc nevypadá jako M&M stránky, ne?)

Asi bych napsal popisnější hlášku, vynechal bych tu část z orgem, a naopak bych tam připsal, že nejsi přihlášený (to se stane asi častěji než že bych se dostal na špatný kontaktníček). Také si nejsem jistý, jestli HttpResponse je to správné. (Jakože vrátí to něco, co moc nevypadá jako M&M stránky, ne?)

Uh, je to ekvivalentní s if request.user not in […] and not request.user.is_org:?

Uh, je to ekvivalentní s `if request.user not in […] and not request.user.is_org:`?
if not request.user.je_org: # nebyl jsi tam, nebo nejsi org raise PermissionDenied()
raise Http404() # není k dispozici
if not soustredeni.kontaktnicek_pdf and typ == "pdf": # není k dispozici if (not soustredeni.kontaktnicek_pdf and typ == "pdf") or (not soustredeni.kontaktnicek_vcf and typ == "vcf"):

404 není správný návratový kód (kontaktníček zjevně existuje, ale nemám k němu přístup), má být 403 (PermissionDenied se myslím jmenuje ta Djangová výjimka).

404 není správný návratový kód (kontaktníček zjevně existuje, ale nemám k němu přístup), má být 403 (`PermissionDenied` se myslím jmenuje ta Djangová výjimka).
raise Http404()
elif not soustredeni.kontaktnicek_vcf and typ == "vcf": # není k dispozici
raise Http404() raise Http404()

Poněkud se mi nelíbí místní duplikace kódu, když se tam mění dohromady tři věci (až přidáme další, tak někde něco zapomeneme přepsat a bude to bug…). Co třeba:

# typ -> (field, mime_type, otevreni)
kontaktnicky = {
|   'pdf': (soustredeni.kontaktnicek_pdf, 'applcation/pdf', 'rb'),
|   'vcf': (soustredeni.kontaktnicek_vcf, 'text/vcard', 'r'), # vcf je texťák, nevím, jestli je potřeba ho otevítat binárně.
}
try:
	field, mime, otevreni = kontaktnicky[typ]
except KeyError as e:
	raise ValueError("Neznámý typ kontaktníčku") from e
if not field:
|   ...
with open(field.path, otevreni) as soubor:
|   return HttpResponse(soubor.read(), content_type=mime)
Poněkud se mi nelíbí místní duplikace kódu, když se tam mění dohromady tři věci (až přidáme další, tak někde něco zapomeneme přepsat a bude to bug…). Co třeba: ```python3 # typ -> (field, mime_type, otevreni) kontaktnicky = { | 'pdf': (soustredeni.kontaktnicek_pdf, 'applcation/pdf', 'rb'), | 'vcf': (soustredeni.kontaktnicek_vcf, 'text/vcard', 'r'), # vcf je texťák, nevím, jestli je potřeba ho otevítat binárně. } try: field, mime, otevreni = kontaktnicky[typ] except KeyError as e: raise ValueError("Neznámý typ kontaktníčku") from e if not field: | ... with open(field.path, otevreni) as soubor: | return HttpResponse(soubor.read(), content_type=mime) ```

Uh, ten if not field: ... byl náznak toho, že není potřeba výčet typů v if (not soustredeni.kontaktnicek_pdf and typ == "pdf") or (not soustredeni.kontaktnicek_vcf and typ == "vcf"):, sorry za neexplicitnost.

Uh, ten `if not field: ...` byl náznak toho, že není potřeba výčet typů v `if (not soustredeni.kontaktnicek_pdf and typ == "pdf") or (not soustredeni.kontaktnicek_vcf and typ == "vcf"):`, sorry za neexplicitnost.
if typ == "pdf": kontaktnicky = {
with open(soustredeni.kontaktnicek_pdf.path, 'rb') as pdf: 'pdf': (soustredeni.kontaktnicek_pdf, 'applcation/pdf', 'rb'),
response = HttpResponse(pdf.read(), content_type='application/pdf') 'vcf': (soustredeni.kontaktnicek_vcf, 'text/vcard', 'rb'), # vcf je texťák, nevím, jestli je potřeba ho otevítat binárně.
return response }
elif typ == "vcf":

Možno rovnou:

with open() as whatever:
	return HttpResponse()
Možno rovnou: ```python3 with open(…) as whatever: return HttpResponse(…) ```
with open(soustredeni.kontaktnicek_vcf.path, 'rb') as vcf: try:
response = HttpResponse(vcf.read(), content_type='text/vcard') field, mime, otevreni = kontaktnicky[typ]
return response except KeyError as e:
else: raise ValueError("Neznámý typ kontaktníčku") from e
raise ValueError("Nepodporovaný typ kontaktníčku")
with open(field.path, otevreni) as kontaktnicek:
response = HttpResponse(kontaktnicek.read(), content_type=mime)
response['Content-Disposition'] = 'attachment; filename="kontaktnicek.{}"'.format(typ)
return response