Merge branch 'develop' into django3.2
This commit is contained in:
		
						commit
						882f8e2228
					
				
					 27 changed files with 359 additions and 66 deletions
				
			
		|  | @ -16,7 +16,7 @@ | |||
| 	}, | ||||
| 	{ | ||||
| 		"fields": { | ||||
| 			"content": "<h1 id=\"co-je-mm\">Co je M&M?</h1>\r\n\r\n<h3 id=\"mm-je-mezioborový-korespondenční-seminář-pro-středoškoláky\">M&M je mezioborový korespondenční seminář pro středoškoláky</h3>\r\n\r\n<p style=\"text-align: justify;\">Ptáš se, co že je to ten korespondenční seminář? Je to jednoduché, zamysli se nad <a href=\"/aktualni/zadani/\">zadanou úlohou či problémem</a>, <a href=\"/resitel/nahraj_reseni\">odevzdej řešení</a>, my ti jej opravíme a pošleme zpět. Nabízíme témata z různých oblastí matematiky, fyziky, informatiky i dalších oborů, takže si u nás určitě najdeš to svoje. Při řešení si můžeš vyzkoušet, jak vypadá vědecká práce, a mnoho zajímavého se naučit. Podívej se na tipy v sekci <a href=\"/jak-resit/\">Jak řešit</a> a pusť se do toho! Můžeš se připojit kdykoliv během roku.</p>\r\n\r\n<h3 id=\"mm-jsou-témata\">M&M jsou témata</h3>\r\n\r\n<p style=\"text-align: justify;\">Jádro M&M tvoří takzvaná témata, tedy texty doplněné o úlohy a náměty vyzývající k přemýšlení a experimentování. Přijímáme i originální přístup k problémům, takže můžeš například vyřešit fyzikální problém naprogramováním simulace. v minulých letech řešitelé sestavovali spektrometry, pomocí laserových ukazovátek měřili index lomu různých látek, zkoumali křivky popisující vývoj počtu cestujících v tramvaji v průběhu cesty nebo programovali strategie v jednoduché hře a pak je nechávali soupeřit v turnajích. Podívej se, jaká témata nabízíme <a href=\"/aktualni/zadani/\">právě teď</a>.</p>\r\n\r\n<h3 id=\"mm-je-časopis\">M&M je časopis</h3>\r\n\r\n<p style=\"text-align: justify;\">Zadání a texty od organizátorů vydáváme formou časopisu. Kromě toho zde rovněž otiskujeme řešení a příspěvky našich řešitelů k tématům, články shrnující výsledky <a href=\"/soustredeni/\">konfer</a> – projektů, kterými se zabývali na soustředění, i výsledky jejich vlastního výzkumu. Díky tomu jsme si například mohli přečíst o <a href=\"https://mam.mff.cuni.cz/media/cislo/pdf/25/25-6.pdf#page=45\">Lichtenbergových obrazcích</a> či <a href=\"https://mam.mff.cuni.cz/media/cislo/pdf/23/23-6.pdf#page=19\">gravitaci v placatém světě</a>. Během ročníku obvykle vyjde šest čísel časopisu, prohlédnout si je můžeš v <a href=\"/archiv/rocniky/\">Archivu</a>.</p>\r\n\r\n<h3 id=\"mm-je-soutěž\">M&M je soutěž</h3>\r\n\r\n<p style=\"text-align: justify;\">Ke všem příspěvkům posíláme řešitelům zpětnou vazbu a udělujeme za ně body. Vítězové semináře se mohou těšit na zajímavé knihy a deskové hry, autora nejlepšího otištěného článku každoročně odměňujeme dortem. <a href=\"/o-nas/odmeny/\">Úspěšným řešitelům</a> jsou navíc prominuty přijímací zkoušky na MFF UK.</p>\r\n\r\n<h3 id=\"mm-jsou-soustředění\">M&M jsou soustředění</h3>\r\n\r\n<p style=\"text-align: justify;\">Aktivní řešitelé mají možnost s námi za odměnu jet dvakrát do roka na soustředění. Pojeď taky! Budeš mít možnost strávit týden v přírodě plný odborného programu a nejrůznější zábavy s partou kamarádů. Čekají tě malé vědecké projekty, přednášky, workshopy, šifrovačka, výlet a mnoho dalšího. Chceš-li se dozvědět víc, přečti si stránku <a href=\"/soustredeni/\">Soustředění</a> nebo se podívej na <a href=\"/soustredeni/probehlo/\">fotky</a>.</p>\r\n\r\n<h3 id=\"mm-jsme-my\">M&M jsme my</h3>\r\n\r\n<p style=\"text-align: justify;\">Spolu s řešiteli jsme tu i my, organizátoři. Většina z nás jsou studenti Matfyzu, tedy Matematicko-fyzikální fakulty Univerzity Karlovy. Společně se snažíme předávat dál radost z poznávání zajímavých zákoutí matematiky, fyziky a informatiky a budovat komunitu aktivních lidí, kteří se budou rádi scházet, ať už na soustředěních, víkendovkách či jiných akcích. Chceš nás poznat blíž? Podívej se na stránku <a href=\"/o-nas/organizatori/\">Organizátoři</a> nebo rovnou něco vyřeš a pojeď s námi na soustředění!</p>\r\n\r\n<h3 id=\"zaujali-jsme-tě-zapoj-se-přečti-si-jak-řešit-a-podívej-se-na-aktuální-zadání.-už-se-těšíme-na-tvé-příspěvky\" style=\"text-align: center;\">Zaujali jsme tě? Zapoj se! Přečti si <a href=\"/jak-resit/podrobneji/\">jak řešit</a> a podívej se na <a href=\"/aktualni/zadani/\">aktuální zadání</a>. Už se těšíme na tvé příspěvky!</h3>", | ||||
| 			"content": "<h1 id=\"co-je-mm\">Co je M&M?</h1>\r\n\r\n<h3 id=\"mm-je-mezioborový-korespondenční-seminář-pro-středoškoláky\">M&M je mezioborový korespondenční seminář pro středoškoláky</h3>\r\n\r\n<p style=\"text-align: justify;\">Ptáš se, co že je to ten korespondenční seminář? Je to jednoduché, zamysli se nad <a href=\"/aktualni/zadani/\">zadanou úlohou či problémem</a>, <a href=\"/resitel/nahraj_reseni\">odevzdej řešení</a>, my ti jej opravíme a pošleme zpět. Nabízíme témata z různých oblastí matematiky, fyziky, informatiky i dalších oborů, takže si u nás určitě najdeš to svoje. Při řešení si můžeš vyzkoušet, jak vypadá vědecká práce, a mnoho zajímavého se naučit. Podívej se na tipy v sekci <a href=\"/jak-resit/\">Jak řešit</a> a pusť se do toho! Můžeš se připojit kdykoliv během roku.</p>\r\n\r\n<h3 id=\"mm-jsou-témata\">M&M jsou témata</h3>\r\n\r\n<p style=\"text-align: justify;\">Jádro M&M tvoří takzvaná témata, tedy texty doplněné o úlohy a náměty vyzývající k přemýšlení a experimentování. Přijímáme i originální přístup k problémům, takže můžeš například vyřešit fyzikální problém naprogramováním simulace. V minulých letech řešitelé sestavovali spektrometry, pomocí laserových ukazovátek měřili index lomu různých látek, zkoumali křivky popisující vývoj počtu cestujících v tramvaji v průběhu cesty nebo programovali strategie v jednoduché hře a pak je nechávali soupeřit v turnajích. Podívej se, jaká témata nabízíme <a href=\"/aktualni/zadani/\">právě teď</a>.</p>\r\n\r\n<h3 id=\"mm-je-časopis\">M&M je časopis</h3>\r\n\r\n<p style=\"text-align: justify;\">Zadání a texty od organizátorů vydáváme formou časopisu. Kromě toho zde rovněž otiskujeme řešení a příspěvky našich řešitelů k tématům, články shrnující výsledky <a href=\"/soustredeni/\">konfer</a> – projektů, kterými se zabývali na soustředění, i výsledky jejich vlastního výzkumu. Díky tomu jsme si například mohli přečíst o <a href=\"https://mam.mff.cuni.cz/media/cislo/pdf/25/25-6.pdf#page=45\">Lichtenbergových obrazcích</a> či <a href=\"https://mam.mff.cuni.cz/media/cislo/pdf/23/23-6.pdf#page=19\">gravitaci v placatém světě</a>. Během ročníku obvykle vyjde šest čísel časopisu, prohlédnout si je můžeš v <a href=\"/archiv/rocniky/\">Archivu</a>.</p>\r\n\r\n<h3 id=\"mm-je-soutěž\">M&M je soutěž</h3>\r\n\r\n<p style=\"text-align: justify;\">Ke všem příspěvkům posíláme řešitelům zpětnou vazbu a udělujeme za ně body. Vítězové semináře se mohou těšit na zajímavé knihy a deskové hry, autora nejlepšího otištěného článku každoročně odměňujeme dortem. <a href=\"/o-nas/odmeny/\">Úspěšným řešitelům</a> jsou navíc prominuty přijímací zkoušky na MFF UK.</p>\r\n\r\n<h3 id=\"mm-jsou-soustředění\">M&M jsou soustředění</h3>\r\n\r\n<p style=\"text-align: justify;\">Aktivní řešitelé mají možnost s námi za odměnu jet dvakrát do roka na soustředění. Pojeď taky! Budeš mít možnost strávit týden v přírodě plný odborného programu a nejrůznější zábavy s partou kamarádů. Čekají tě malé vědecké projekty, přednášky, workshopy, šifrovačka, výlet a mnoho dalšího. Chceš-li se dozvědět víc, přečti si stránku <a href=\"/soustredeni/\">Soustředění</a> nebo se podívej na <a href=\"/soustredeni/probehlo/\">fotky</a>.</p>\r\n\r\n<h3 id=\"mm-jsme-my\">M&M jsme my</h3>\r\n\r\n<p style=\"text-align: justify;\">Spolu s řešiteli jsme tu i my, organizátoři. Většina z nás jsou studenti Matfyzu, tedy Matematicko-fyzikální fakulty Univerzity Karlovy. Společně se snažíme předávat dál radost z poznávání zajímavých zákoutí matematiky, fyziky a informatiky a budovat komunitu aktivních lidí, kteří se budou rádi scházet, ať už na soustředěních, víkendovkách či jiných akcích. Chceš nás poznat blíž? Podívej se na stránku <a href=\"/o-nas/organizatori/\">Organizátoři</a> nebo rovnou něco vyřeš a pojeď s námi na soustředění!</p>\r\n\r\n<h3 id=\"zaujali-jsme-tě-zapoj-se-přečti-si-jak-řešit-a-podívej-se-na-aktuální-zadání.-už-se-těšíme-na-tvé-příspěvky\" style=\"text-align: center;\">Zaujali jsme tě? Zapoj se! Přečti si <a href=\"/jak-resit/podrobneji/\">jak řešit</a> a podívej se na <a href=\"/aktualni/zadani/\">aktuální zadání</a>. Už se těšíme na tvé příspěvky!</h3>", | ||||
| 			"enable_comments": false, | ||||
| 			"registration_required": false, | ||||
| 			"sites": [ | ||||
|  |  | |||
							
								
								
									
										173
									
								
								docs/zapisy/2021-12-06-testovani_dokumentace_codereview.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								docs/zapisy/2021-12-06-testovani_dokumentace_codereview.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,173 @@ | |||
| # Postup zkrášlení kódu M&Mího webu | ||||
| 
 | ||||
| ## Obecně o webu | ||||
| 
 | ||||
| - Python, Django, spousta nějakých rozšíření, frontend HTML + CSS + trocha JS | ||||
| - Velké břímě historie, kterou nejspíš nechceme zahodit | ||||
|     - Změny v M&M někdy dost zamotají potřebný kód (tituly) | ||||
| - Občas je potřeba dělat opravy rychle | ||||
| 
 | ||||
| ## Aktuální stav | ||||
| 
 | ||||
| - Zběsile zbastlený kód | ||||
|     - „Co je to ‚single responsibility principle‘?“ ☺ | ||||
| - Dost netriviální množství objektů a jejich vazeb | ||||
|     - Dost možná do velké míry inherentní složitost | ||||
| - Webaři aktuálně relativně zběhlí v programování (ale je potřeba myslet na to, že to tak být nemusí) | ||||
| - Webaři stárnou (Jethro, Kristý, Anet) a mizí (Pavel, Káťa), je potřeba web připravit na předání | ||||
| - Kód je rozdělený mezi orgy a jeden „nerozumí“ tomu, co druhý napsal (musí to vyčíst z kódu, nezná souvislosti, …) | ||||
|     - Noví orgové se aktuálně musí ptát, což je jim nepříjemné a nutí je umět formulovat dotazy | ||||
| 
 | ||||
| ### Invarianty | ||||
| 
 | ||||
| - Není to práce, ale zábava-ish → libovolný proces nesmí být (moc) na obtíž. | ||||
|     - I malé nepohodlí je potřeba vyvážit relativně velkým přínosem | ||||
|         - nebo dostatečně zřejmou vidinou budoucího pohodlí / minimalizace nepohodlí | ||||
| - Nejsme programátoři, spíš jsme bastlíři kódu (kteří znají rozumnou podmnožinu syntaxe Pythonu) | ||||
|     - Zvlášť noví orgové | ||||
|     - Nechceme cílit na mega-profi kód, je to nedosažitelný cíl | ||||
|         - Nejspíš to do nějaké míry ubastlené bude pořád, ta míra závisí na zkušenosti aktuálních webařů | ||||
|     - Nástroje nás nesmí moc mást. | ||||
| - Děláme to zadarmo jeden večer v týdnu | ||||
|     - Vývoj jde pomalu, často pomaleji než vývoj knihoven | ||||
|         - → kód se rozbíjí i sám | ||||
| - Běží to na Gimlim | ||||
|     - Debian (old)stable → nemůžeme používat moc nové featury Pythonu | ||||
|         - Aktuálně Python 3.7.3 | ||||
| - Webaři jsou náhodně vzniklá skupina lidí. | ||||
|     - Různé nástroje, různé operační systémy | ||||
|     - Nechceme vynucovat konkrétní metody, multiplatformní nástroje asi požadovat můžeme | ||||
|     - Na serveru může běžet cokoliv, co tam jde rozběhnout | ||||
|     - Kód by neměl být moc složitý / matoucí / kompaktní (?) | ||||
|         - případně fakt hodně okomentovaný | ||||
|      | ||||
| ## O co se snažíme | ||||
| 
 | ||||
| - Zpřístupnit vývoj novým webařům | ||||
| - Umožnit chápání i cizího kódu co nejjednodušeji | ||||
| - Nevzít si s sebou implementační tajemství ~~do hrobu~~ pryč z M&Mka | ||||
| 
 | ||||
| ```graphviz | ||||
| digraph "Závislosti věcí" { | ||||
|     ss -> sdil -> doku -> cs; | ||||
|     ss -> cit ->ref -> cs; | ||||
|     ref -> nrt -> tst -> cs; | ||||
|     sdil -> cr -> cs | ||||
|     ss -> nrt; | ||||
|     ss[label="Současný stav",shape=box]; | ||||
|     cit[label="čitelný kód"]; | ||||
|     cs[label="Cílový stav",shape=box]; | ||||
|     ref[label="refactoring"]; | ||||
|     nrt[label="nerozbít to"]; | ||||
|     tst[label="testy"]; | ||||
|     doku[label="dokumentace (vývojářská)"]; | ||||
|     sdil[label="chápání kódu ostatních / stávajícího"]; | ||||
|     cr[label="code review"]; | ||||
|     nrt,sdil,cit[shape=hexagon]; | ||||
|     tst,doku,cr[color=blue]; | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ## Code review | ||||
| 
 | ||||
| Aktuálně: Pavel občas z rozmaru čte diffy; párkrát jsme zkoušeli [programovat v páru](https://mam.mff.cuni.cz/wiki/Web/Tipy/PairProgramming), je to relativně časově náročné. | ||||
| 
 | ||||
| - Nevynucovat | ||||
| - Primární motivace je umožnit nějak vidět změny a případně k nim dávat komentáře, jak stylu „tohle mi není jasné“, tak i „tohle by chtělo přepsat“. | ||||
| - Chceme hlavně vytvořit příležitost ke čtení cizího kódu a seznamování se s ním (i v zájmu zaučování nových webařů) | ||||
| 
 | ||||
| ### Názory | ||||
| 
 | ||||
| - spíš post-hoc | ||||
| - Možná code-review toho, co jde na produkci | ||||
| - Chceme umět komentovat konkrétní řádky kódu | ||||
| 
 | ||||
| - Gitea/gitlab? | ||||
|     - Klikátko a barevný řádky a vyhledávání jsou fajn (gitlab, gitea) | ||||
|         - Jethro: je fajn umět skočit na definici | ||||
|     - Kombinace s CI | ||||
|     - Pokud bude gitea v něčem nedostatečná, tak hrozí, že bude potřeba migrovat znovu, což je nepraktické | ||||
|     - Gitlab je asi častější než gitea → je lepší názor si na to zvyknout | ||||
|      | ||||
| __Závěr:__ Zkusíme to hodit do GitLabu (nejspíš veřejného\*), zavedeme pull-requesty do `master` větve, náhodně se budeme přiřazovat a používat ho nějak intuitivně. | ||||
| 
 | ||||
| \*: Ve fakultním neumíme přidávat další uživatele, v KAMím zas možná není CI. | ||||
| 
 | ||||
| ## Testy | ||||
| 
 | ||||
| Aktuálně: pár testů na dohromady řádově 4 funkce, drobný pokus o TDD, jenž narazil na úskalí reálného světa. Lokální spuštění testů trvá relativně dlouho, nejspíš kvůli spoustě migrací. | ||||
| 
 | ||||
| - Potřebujeme ověřit, že to funguje a že to _pořád_ funguje | ||||
| 
 | ||||
| - CI? Coverage? | ||||
| 
 | ||||
| ### Názory | ||||
| 
 | ||||
| - PyTest je fajn | ||||
| - Testovat frontend? | ||||
|     - Jethro: při nasazení by se mohly dělat screenshoty celých vybraných stránek přes Selenium (nebo obdobné) a hlásit rozdíly | ||||
| 
 | ||||
| __Závěr:__ Backend testujeme PyTestem (`./manage.py test`), u frontendu výhledově zkusíme ty vizuální diffy a pak se uvidí, CI podle webového klikátka na code review. Bylo by dobré mít rozumná testdata, ať se nemusí mockovat moc věcí.  | ||||
| 
 | ||||
| ## Formát kódu | ||||
| 
 | ||||
| Aktuálně: Jakýsi coding style zhruba existuje, není popsaný, šíří se lidovou slovesností. | ||||
| 
 | ||||
| - Nesmí být striktně vynucovaný | ||||
| - Musel by být hodně nastavitelný | ||||
|     - Nechceme mít kód plný `#NOQA: WTF42` | ||||
| - Nejspíš vždycky bude mít false positives (`seminar.utils.roman_numerals`) i false negatives (`seminar.models.tvorba.Cislo.posli_cislo_mailem`) | ||||
|     - Možná dobrý sluha, ale určitě špatný pán (also: špatná zkušenost ☺) | ||||
| - __Důsledek:__ Hrozí, že těch falešných varování bude moc, čímž to ztratí smysl úplně | ||||
|     - Potenciálně by šlo aplikovat jen lokálně na změny? | ||||
| 
 | ||||
| ### Názory | ||||
| 
 | ||||
| - P: nemyslím si, že zvládneme mít „průhledný kód“ (dostatečně konzistentní kód, aby ho člověk přestal vnímat a spíš viděl myšlenky). | ||||
| 
 | ||||
| - P: Kecadla do kódu trochu zavání větším peklem než užitkem (takže black a flake8 jsou ze hry); isort možná dává smysl; je otázka, jestli použít mypy, ale typové značky v kódu spíš chceme (zvlášť u věcí, které nejsou prostě django view – typicky utils.) | ||||
|     - J: Divné (=Pavlovo) groupování importů je spíš matoucí, spíš moc nepomáhalo | ||||
| 
 | ||||
| - P (doplněno zpětně): pydocstyle vynucuje PEP-257, který se možná tluče se sphinxem… | ||||
| - P (též zpětně): Možná by se mohl dát použít pylint, tomu jde aspoň vysvětlit coding style a nerazí tupě PEP-8, ale nastavovat ho je asi větší porod, než jak moc pomůže… | ||||
| 
 | ||||
| __Závěr:__ Kecadla na formát spíš nechceme; isort by mohl být fajn, ale bylo by dobré mít rozdělené bloky „náš kód“, „standardní knihovna“ a „Django a další balíčky z PyPA“; u našeho kódu (utils, obecně ne-Django věci) chceme držet záměr (na úrovni dohody) psát signatury funkcí a v případě jejich přítomnosti se nechat varovat při porušení signatury. | ||||
| 
 | ||||
| - P (večerní prokrastinace): Bandit vypadá, že hlásí jen strašně obvious věci by default, nepřijde mi jako moc úžasné vylepšení. Do CI možná dobrý | ||||
| 
 | ||||
| ## Dokumentace | ||||
| 
 | ||||
| Aktuálně: něco málo je na wiki (`/Web/`), občas má nějaká funkce docstring, obecně je toho málo | ||||
| 
 | ||||
| ### Požadavky | ||||
| 
 | ||||
| - Jedno autoritativní místo a dá se najít | ||||
| - Dostatečně „blízko“ kódu | ||||
|     - nastavit mindset na psaní dokumentace „rovnou“? | ||||
| - Umožnit i obecný text, ne jen komentáře kódu (modulů, funkcí) | ||||
| 
 | ||||
| 
 | ||||
| ### Bonusy | ||||
| 
 | ||||
| - Zajišťování konzistence s uživatelskou dokumentací | ||||
|     - aktuálně wiki | ||||
| - Podpora i dalších jazyků (Vue, Javascript, CSS, možná django-templates) | ||||
| 
 | ||||
| ### Názory | ||||
| 
 | ||||
| - Jde to dělat sphinxem | ||||
|     - Stínovlas by mohl vědět v CZ.NICu se sphinx jede. Případně zkusit zjistit, co umí jejich Akademie | ||||
| - Free-textová dokumentace (architektura ap.) má být nezávislá na dokumentaci konkrétního kódu, ale je fajn, když se to pak spojí dohromady, jde-li to. | ||||
|     - Lepší, když se obojí dá dělat stejným nástrojem | ||||
| - Káťa má někdy pocit, že tráví spoustu času tím, že hledá který soubor vůbec upravit; to má v naší dokumentaci být. | ||||
| 
 | ||||
| __Závěr:__ Zkusíme použít sphinx (z nedostatku vlastních zkušeností a kvůli jeho popularitě), když se nám to nebude líbit, tak budeme řešit dál. Bylo by fajn najít nějaký workshop, bude to rychlejší nalejvárna než číst dokumentaci. V krátkodobém výhledu stáhneme vývojovou dokumentaci z webu do repozitáře a zprovozníme někde automatické buildy (aby se dala číst jako člověk a ne jako stroj). | ||||
| 
 | ||||
| ## Uživatelská dokumentace | ||||
| 
 | ||||
| - K: Dělat ji ve spolupráci s těma uživatelema | ||||
| - P: Dávný Hedgedoc může případně sloužit jako základ osnovy | ||||
| - K: Dost možná nevíme, co bolí víc a co míň | ||||
| - Jethro: Musí být na wiki, jinak tím zmateme oržstvo | ||||
| 
 | ||||
| __Závěr:__ Dokumentace bude na wiki (<https://mam.mff.cuni.cz/wiki/Web_user/Dokumentace>, výhledově možná ve stejné složce v dalších souborech), bude vznikat podle našich pocitů a dotazů od ostatních; výhledově bude schůzka na ukázání featur nového webu a tam se dosbírají náměty na to, co sepsat. | ||||
|  | @ -62,11 +62,12 @@ | |||
|         </div> | ||||
|       {% endwith %} | ||||
|     {% endif%} | ||||
|     <span id="nahoru" class="kotva_obrazku"></span> | ||||
|     <img src="{{obrazek.obrazek_stredni.url}}" | ||||
|          height="{{vyska}}" | ||||
|          width="{{sirka}}" | ||||
|          alt="{{obrazek.popis}}" | ||||
|          class="obrazek" id="nahoru"> | ||||
|          class="obrazek"> | ||||
|           | ||||
|     {% if obrazky_dalsi %} | ||||
|       {% with obrazky_dalsi|first as dalsi_obrazek %} | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ from django.contrib import admin | |||
| from reversion.admin import VersionAdmin | ||||
| from korektury.models import KorekturovanePDF | ||||
| 
 | ||||
| from django.core.mail import send_mail | ||||
| from django.urls import reverse | ||||
| 
 | ||||
| # Register your models here. | ||||
| class KorekturovanePDFAdmin(VersionAdmin): | ||||
|  | @ -16,11 +18,31 @@ class KorekturovanePDFAdmin(VersionAdmin): | |||
| 	fieldsets = [ | ||||
| 			(None, | ||||
| 				{'fields': | ||||
| 					['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar']}), | ||||
| 					['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar', 'poslat_mail']}), | ||||
| 			# (u'PDF',       {'fields': ['pdf']}), | ||||
| 				] | ||||
| 	list_display = ['nazev', 'cas', 'stran', 'org'] | ||||
| 	list_filter = [] | ||||
| 	search_fields = [] | ||||
| 
 | ||||
| 	def save_model(self, request, obj, form, change): | ||||
| 		super().save_model(request, obj, form, change) | ||||
| 		if not change and obj.poslat_mail: # Je nový a má se poslat mail | ||||
| 			odkaz = request.build_absolute_uri(reverse('korektury', kwargs={'pdf': obj.id})) | ||||
| 			odesilatel = 'korekturovatko-nove-pdf@mam.mff.cuni.cz' | ||||
| 			prijemce = 'org@mam.mff.cuni.cz' | ||||
| 			predmet = f'Nové korektury: {obj.nazev}' | ||||
| 			text = f'''\ | ||||
| V korekturovátku se objevil nový soubor: {obj.nazev} | ||||
| {odkaz} | ||||
| 
 | ||||
| Popis souboru: | ||||
| {obj.komentar} | ||||
| 
 | ||||
| --- | ||||
| S pozdravem a korekturám zdar! | ||||
| Korekturovátko | ||||
| ''' | ||||
| 			send_mail(predmet,text,odesilatel,[prijemce]) | ||||
| 
 | ||||
| admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin) | ||||
|  |  | |||
							
								
								
									
										18
									
								
								korektury/migrations/0018_korekturovanepdf_poslat_mail.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								korektury/migrations/0018_korekturovanepdf_poslat_mail.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| # Generated by Django 2.2.24 on 2021-12-05 23:09 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('korektury', '0017_auto_20190610_2358'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='korekturovanepdf', | ||||
|             name='poslat_mail', | ||||
|             field=models.BooleanField(default=True, help_text='Určuje, zda se má o nově nahraném PDF poslat e-mail do mam-org. Při upravování existujícího souboru už nemá žádný vliv.', verbose_name='Poslat mail o novém PDF'), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -63,6 +63,10 @@ class KorekturovanePDF(models.Model): | |||
| 	status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False, | ||||
| 			default = STATUS_PRIDAVANI) | ||||
| 
 | ||||
| 	poslat_mail = models.BooleanField('Poslat mail o novém PDF', default=True, | ||||
| 			help_text='Určuje, zda se má o nově nahraném PDF poslat e-mail do mam-org. Při upravování existujícího souboru už nemá žádný vliv.', | ||||
| 			) | ||||
| 
 | ||||
| 
 | ||||
| 	#TODO Nepovinný foreign key k číslu | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ | |||
| 	<i>{{pdf.komentar}}</i> | ||||
| 	<br> | ||||
| 	<i>Klikni na chybu, napiš komentář</i>  | | ||||
| 	<a href="{{pdf.pdf.url}}">stáhnout PDF (bez korektur)</a> | | ||||
| 	<a href="../">seznam souborů</a> | | ||||
| 	<a href="/admin/korektury/korekturovanepdf/">Spravovat PDF</a> | | ||||
| 	<a href="../help">nápověda</a> | | ||||
|  |  | |||
|  | @ -22,9 +22,8 @@ | |||
| <ul> | ||||
|   {% for pdf in skupina.list %} | ||||
| 	  <li><span {% if pdf.status == 'zanaseni'%} class="comitting-text" {% elif pdf.status == 'zastarale' %} class="deprecated-text" {% endif %}> | ||||
| 	  	<b>{{ pdf.nazev }}</b> | ||||
|         <b><a href="/korektury/{{pdf.id}}">{{ pdf.nazev }}</a></b> | ||||
| 		<i>{{pdf.komentar}}</i> | ||||
| 		<a href="/korektury/{{pdf.id}}">{{pdf.pdf.name}}</a> | ||||
| 		(k opravě: {{pdf.k_oprave_cnt}},  | ||||
| 		opraveno: {{pdf.opraveno_cnt}}, | ||||
| 		není chyba: {{pdf.neni_chyba_cnt}}, | ||||
|  |  | |||
|  | @ -166,7 +166,7 @@ class KorekturyView(generic.TemplateView): | |||
| 		texty = [(oprava.autor.osoba.plne_jmeno(),oprava.text)] | ||||
| 		for kom in Komentar.objects.filter(oprava=oprava): | ||||
| 			texty.append((kom.autor.osoba.plne_jmeno(),kom.text)) | ||||
| 		optext = "\n".join([": ".join(t) for t in texty]) | ||||
| 		optext = "\n\n\n".join([": ".join(t) for t in texty]) | ||||
| 		text = u"Text komentáře:\n\n{}\n\n=== Konec textu komentáře ===\n\ | ||||
| 				\nodkaz do korekturovátka: {}\n\ | ||||
| 				\nVaše korekturovátko\n".format(optext, odkaz) | ||||
|  |  | |||
|  | @ -336,3 +336,16 @@ CISLO_IMG_DIR = os.path.join('cislo', 'img') | |||
| 
 | ||||
| # E-MAIL NOTIFICATIONS | ||||
| POSLI_MAILOVOU_NOTIFIKACI = False | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # Logování chyb | ||||
| class InvalidTemplateVariable(str): | ||||
|     def __mod__(self, variable): | ||||
|         import logging | ||||
|         logger = logging.getLogger(__name__) | ||||
|         logger.warning("Proměnná '%s' neexistuje" % variable) | ||||
|         return '' | ||||
| TEMPLATES[0]['OPTIONS']['string_if_invalid'] = InvalidTemplateVariable('%s') | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,10 @@ src: url("../fonts/OpenSans/OpenSans-Regular.ttf"); | |||
| font-weight: normal; | ||||
| } | ||||
| 
 | ||||
| p { | ||||
| 	text-align: justify; | ||||
| } | ||||
| 
 | ||||
| body { | ||||
| 	font-family: 'OpenSans'; | ||||
| 	background-color: #fffbf6; | ||||
|  | @ -1113,6 +1117,21 @@ div.zadani_termin .datum { | |||
|     float: right; | ||||
| } | ||||
| 
 | ||||
| /* posune kotvu obrázku v galerii o oranžový pruh dolu, aby se pod ním obrázek neschovával */ | ||||
| /* https://stackoverflow.com/questions/10732690/offsetting-an-html-anchor-to-adjust-for-fixed-header */ | ||||
| .kotva_obrazku { | ||||
| 	display: block; | ||||
| 	position: relative; | ||||
| 	width: 0; | ||||
| 	height: 55px; /* viz #title */ | ||||
| 	margin-top: -55px; /* viz #title */ | ||||
| } | ||||
| @media(max-width: 860px) { | ||||
| 	.kotva_obrazku { | ||||
| 		height: 3em; /* #FIXME nemám páru, jak zjistit výšku toho elementu */ | ||||
| 		margin-top: -3em; /* #FIXME */ | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /**/ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,19 +1,16 @@ | |||
| {% extends "base.html" %} | ||||
| {% extends "error_base.html" %} | ||||
| 
 | ||||
| {% load staticfiles %} | ||||
| 
 | ||||
| {% block content %} | ||||
|   <h2> | ||||
|     {% block nadpis1a %}{% block nadpis1b %} | ||||
| {% block errorheading %} | ||||
|       O-jo-jo-jo-joj | ||||
|     {% endblock %}{% endblock %} | ||||
|   </h2> | ||||
| {% endblock %} | ||||
| 
 | ||||
|   <p> | ||||
| {% block errortext %} | ||||
|     Chybička se vloudila. | ||||
|     Zkuste přejít na <a href="/">titulní stránku</a> | ||||
|     nebo se podívat na <a href="{% url 'seminar_aktualni_zadani' %}">aktuální zadání</a>. | ||||
|   </p> | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block errorimage %} | ||||
|   <img src="{% static '500.png' %}"> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,19 +1,16 @@ | |||
| {% extends "base.html" %} | ||||
| {% extends "error_base.html" %} | ||||
| 
 | ||||
| {% load staticfiles %} | ||||
| 
 | ||||
| {% block content %} | ||||
|   <h2> | ||||
|     {% block nadpis1a %}{% block nadpis1b %} | ||||
| {% block errorheading %} | ||||
|       Vrrrrrrrrr | ||||
|     {% endblock %}{% endblock %} | ||||
|   </h2> | ||||
| {% endblock %} | ||||
| 
 | ||||
|   <p> | ||||
| {% block errortext %} | ||||
|     Tady pravděpodobně nemáte co dělat. | ||||
|     Zkuste přejít na <a href="/">titulní stránku</a> | ||||
|     nebo se podívat na <a href="{% url 'seminar_aktualni_zadani' %}">aktuální zadání</a>. | ||||
|   </p> | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block errorimage %} | ||||
|   <img src="{% static '500.png' %}"> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,19 +1,16 @@ | |||
| {% extends "base.html" %} | ||||
| {% extends "error_base.html" %} | ||||
| 
 | ||||
| {% load staticfiles %} | ||||
| 
 | ||||
| {% block content %} | ||||
|   <h2> | ||||
|     {% block nadpis1a %}{% block nadpis1b %} | ||||
|       Požadovaná stránka nenalezena | ||||
|     {% endblock %}{% endblock%} | ||||
|   </h2> | ||||
| 
 | ||||
|   <p> | ||||
|     Tuto stránku jsme na našem serveru nenalezli. | ||||
|     Zkuste přejít na <a href="/">titulní stránku</a> | ||||
|     nebo se podívat na <a href="{% url 'seminar_aktualni_zadani' %}">aktuální zadání</a>. | ||||
|   </p> | ||||
|   <img src="{% static '404.png' %}"> | ||||
| {% block errorheading %} | ||||
| Požadovaná stránka nenalezena | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block errortext %} | ||||
| Tuto stránku jsme na našem serveru nenalezli. | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block errorimage %} | ||||
| <img src="{% static '404.png' %}"> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,20 +1,16 @@ | |||
| {% extends "base.html" %} | ||||
| {% extends "error_base.html" %} | ||||
| 
 | ||||
| {% load staticfiles %} | ||||
| 
 | ||||
| {% block content %} | ||||
|   <h2> | ||||
|     {% block nadpis1a %}{% block nadpis1b %} | ||||
| {% block errorheading %} | ||||
|       O-jo-jo-jo-joj | ||||
|     {% endblock %}{% endblock %} | ||||
|   </h2> | ||||
| {% endblock %} | ||||
| 
 | ||||
|   <p> | ||||
| {% block errortext %} | ||||
|     Chybička se vloudila. | ||||
|     Zkuste přejít na <a href="/">titulní stránku</a> | ||||
|     {# Při pádu webu nechceme, aby se rozbily odkazy, nevěříme URLconfu. #} | ||||
|     nebo se podívat na <a href="/aktualni/zadani/">aktuální zadání</a>. | ||||
|   </p> | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block errorimage %} | ||||
|   <img src="{% static '500.png' %}"> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
|     <title>{% block title %}{% block nadpis1a %}{% endblock %} – Korespondenční seminář M&M{% endblock title %}</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <link rel="shortcut icon" href="{% static 'images/MATFYZ_MM_barevne.svg' %}" type="image/x-icon"> | ||||
|     {% render_block css %} | ||||
| {#    {% render_block css %}#} | ||||
|     {% block custom_css %}{% endblock %} | ||||
|     <link href="{% static 'css/bootstrap-theme.css' %}" rel="stylesheet"> | ||||
|     <link href="{% static 'css/bootstrap.css' %}" rel="stylesheet"> | ||||
|  |  | |||
							
								
								
									
										19
									
								
								mamweb/templates/error_base.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								mamweb/templates/error_base.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| {% extends "base.html" %} | ||||
| 
 | ||||
| {% block content %} | ||||
|   <h2> | ||||
|     {% block nadpis1a %}{% block nadpis1b %} | ||||
|     {% block errorheading %} | ||||
|     {% endblock %} | ||||
|     {% endblock %}{% endblock%} | ||||
|   </h2> | ||||
| 
 | ||||
|   <p> | ||||
|     {% block errortext %} | ||||
|     {% endblock %} | ||||
|     Zkuste přejít na <a href="/">titulní stránku</a>. | ||||
|   </p> | ||||
|   {% block errorimage %} | ||||
|   {% endblock %} | ||||
| {% endblock %} | ||||
| 
 | ||||
|  | @ -60,5 +60,9 @@ if settings.DEBUG: | |||
| 		path('media/<path:path>', views.static.serve,  # NOQA | ||||
| 			{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), | ||||
| 		path('__debug__/', include(debug_toolbar.urls)), | ||||
| 		path('400.html', TemplateView.as_view(template_name="400.html")), | ||||
| 		path('403.html', TemplateView.as_view(template_name="403.html")), | ||||
| 		path('404.html', TemplateView.as_view(template_name="404.html")), | ||||
| 		path('500.html', TemplateView.as_view(template_name="500.html")), | ||||
| 		] | ||||
| 	urlpatterns += staticfiles_urlpatterns() | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ $(document).ready(function(){ | |||
| 		<td>{{ form.empty_form.problem }}</td> | ||||
| 		<td>{{ form.empty_form.body }}</td> | ||||
| 		<td>{{ form.empty_form.cislo_body }}</td> | ||||
| 		<td><a href="#" class="smazat_hodnoceni" id="id_{{subform.prefix}}-jsremove"><img src="{% static "odevzdavatko/cross.png" %}" alt="Smazat"></a></td> | ||||
| 		<td><a href="#" class="smazat_hodnoceni" id="id_{{form.empty_form.prefix}}-jsremove"><img src="{% static "odevzdavatko/cross.png" %}" alt="Smazat"></a></td> | ||||
| 	</tr> | ||||
| </table> | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import seminar.models as m | |||
| @admin.register(m.Osoba) | ||||
| class OsobaAdmin(admin.ModelAdmin): | ||||
| 	actions = ['synchronizuj_maily', 'udelej_orgem'] | ||||
| 	search_fields = ['jmeno', 'prijmeni', 'prezdivka'] | ||||
| 
 | ||||
| 	def synchronizuj_maily(self, request, queryset): | ||||
| 		for o in queryset: | ||||
|  |  | |||
|  | @ -1,5 +1,8 @@ | |||
| 
 | ||||
| {% if id %} | ||||
| <tr id="{{ id }}" > | ||||
| {% else %} | ||||
| <tr> | ||||
| {% endif %} | ||||
|   <td> | ||||
|     <label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}"> | ||||
|       {{ field.label }}: | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ django-solo | |||
| django-ckeditor | ||||
| django-flat-theme | ||||
| django-taggit | ||||
| django-autocomplete-light | ||||
| django-autocomplete-light>=3.9.0rc1 | ||||
| django-crispy-forms | ||||
| django-imagekit | ||||
| django-polymorphic | ||||
|  |  | |||
							
								
								
									
										24
									
								
								seminar/migrations/0101_auto_20211213_2306.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								seminar/migrations/0101_auto_20211213_2306.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| # Generated by Django 2.2.24 on 2021-12-13 22:06 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('seminar', '0100_auto_20211129_2354'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='nastaveni', | ||||
|             name='aktualni_cislo', | ||||
|             field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='seminar.Cislo', verbose_name='Aktuální číslo'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='soustredeni', | ||||
|             name='typ', | ||||
|             field=models.CharField(choices=[('jarni', 'Jarní soustředění'), ('podzimni', 'Podzimní soustředění'), ('vikend', 'Víkendový sraz'), ('vylet', 'Výlet')], default='podzimni', max_length=16, verbose_name='typ akce'), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -55,10 +55,12 @@ class Soustredeni(SeminarModelBase): | |||
| 	TYP_JARNI = 'jarni' | ||||
| 	TYP_PODZIMNI = 'podzimni' | ||||
| 	TYP_VIKEND = 'vikend' | ||||
| 	TYP_VYLET = 'vylet' | ||||
| 	TYP_CHOICES = [ | ||||
| 		(TYP_JARNI, 'Jarní soustředění'), | ||||
| 		(TYP_PODZIMNI, 'Podzimní soustředění'), | ||||
| 		(TYP_VIKEND, 'Víkendový sraz'), | ||||
| 		(TYP_VYLET, 'Výlet'), | ||||
| 		] | ||||
| 	typ = models.CharField('typ akce', max_length=16, choices=TYP_CHOICES, blank=False, default=TYP_PODZIMNI) | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ import tempfile | |||
| import logging | ||||
| 
 | ||||
| from django.contrib.sites.shortcuts import get_current_site | ||||
| from django.core.files.storage import FileSystemStorage | ||||
| from django.db import models | ||||
| from django.utils import timezone | ||||
| from django.conf import settings | ||||
|  | @ -646,7 +645,7 @@ class Nastaveni(SingletonModel): | |||
| #	aktualni_rocnik = models.ForeignKey(Rocnik, verbose_name='aktuální ročník', | ||||
| #		null=False, on_delete=models.PROTECT) | ||||
| 
 | ||||
| 	aktualni_cislo = models.ForeignKey(Cislo, verbose_name='poslední vydané číslo',  | ||||
| 	aktualni_cislo = models.ForeignKey(Cislo, verbose_name='Aktuální číslo',  | ||||
| 		null=False, on_delete=models.PROTECT) | ||||
| 
 | ||||
| 	@property | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ | |||
| \ifx \skola \empty | ||||
| {} | ||||
| \else | ||||
| \hbox{\tofont{\skola}} | ||||
| \predsunout{\hbox{\tofont{\skola}}} %FIXME Vyřešit jinak (škola bývá dlouhá a tak se nevejde do konce řádku, tak jsem ji hodil doleva) | ||||
| \fi | ||||
| \vskip .2 em | ||||
| \hbox{\tofont{\ulice}} | ||||
|  | @ -98,24 +98,22 @@ | |||
| 
 | ||||
| {% for r in resitele %} | ||||
| 	{% with o=r.osoba %} | ||||
| 	{% with s=r.osoba.skola %} | ||||
| 	{% with s=r.skola %} | ||||
| 	{% spaceless %} | ||||
| 	{% if r.zasilat == "do_skoly" %}  | ||||
| 		{% if r.stat == "CZ" %} | ||||
| 		{% if o.stat == "CZ" %} | ||||
| \obalka{{o.jmeno|sloz}}{{o.prijmeni|sloz}}{{s.nazev|sloz}}{{s.ulice|sloz}}{{s.psc|sloz}}{{s.mesto|sloz}}{{''|sloz}} | ||||
| 		{% else %} | ||||
| \obalka{{o.jmeno|sloz}}{{o.prijmeni|sloz}}{{s.nazev|sloz}}{{s.ulice|sloz}}{{s.psc|sloz}}{{s.mesto|sloz}}{{o.stat.name|sloz}} | ||||
| 		{% endif %} | ||||
| 
 | ||||
| 	{% elif r.zasilat == "domu" %} | ||||
| 		{% if r.stat == "CZ" %} | ||||
| 		{% if o.stat == "CZ" %} | ||||
| \obalka{{o.jmeno|sloz}}{{o.prijmeni|sloz}}{{''|sloz}}{{o.ulice|sloz}}{{o.psc|sloz}}{{o.mesto|sloz}}{{''|sloz}} | ||||
| 		{% else %} | ||||
| \obalka{{o.jmeno|sloz}}{{o.prijmeni|sloz}}{{''|sloz}}{{o.ulice|sloz}}{{o.psc|sloz}}{{o.mesto|sloz}}{{o.stat.name|sloz}} | ||||
| 		{% endif %} | ||||
| 	{% else %} | ||||
| % zasilat: {{r.zasilat}} | ||||
| %\obalka{{r.jmeno|sloz}}{{r.prijmeni|sloz}}{{''|sloz}}{{r.ulice|sloz}}{{r.psc|sloz}}{{r.mesto|sloz}}{{r.stat.name|sloz}} | ||||
| 	{% endif %} | ||||
| 	{% endspaceless %} | ||||
| 	{% endwith %} | ||||
|  |  | |||
|  | @ -292,8 +292,14 @@ def gen_reseni_ulohy(rnd, cisla, uloha, pocet_resitelu, poradi_cisla, resitele_c | |||
| 			res_vyber.remove(resitele[0]) | ||||
| 
 | ||||
| 		# Vytvoření řešení. | ||||
| 		if uloha.cislo_zadani.datum_deadline is not None: | ||||
| 			# combine, abychom dostali plný čas a ne jen datum | ||||
| 			cas_doruceni = datetime.datetime.combine(uloha.cislo_zadani.datum_deadline, datetime.datetime.min.time()) - datetime.timedelta(days=random.randint(0, 40)) - datetime.timedelta(minutes=random.randint(0, 60*24)) | ||||
| 			# astimezone, protože jinak vyhazuje warning o nenastavené TZ | ||||
| 			res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0], cas_doruceni=cas_doruceni.astimezone(datetime.timezone.utc)) | ||||
| 		else: | ||||
| 			res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0]) | ||||
| 		# Problím a řešitele přiřadíme později, ManyToManyField | ||||
| 		# Problém a řešitele přiřadíme později, ManyToManyField | ||||
| 		# se nedá vyplnit v create(). | ||||
| 		res.resitele.set(res_vyber) | ||||
| 		res.save() | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Pavel "LEdoian" Turinsky
						Pavel "LEdoian" Turinsky