diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index bf8b701ed23..ade61ab75da 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,4 @@ +0379e7532fdf3212b1fe22a58826109c23009be3 ca88caa1031c0de545d82de8d90dcae0e03651fb c5cd8783825b5f6384417dac5f3889b4210b7d08 9c19aff7c7561e3a82978a272ecdaad40dda5c00 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1a87425e017..d6ea11e8e06 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,24 +1,25 @@ repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.9.0 + rev: 24.1.0 hooks: - id: black exclude: \.py-tpl$ - repo: https://github.com/adamchainz/blacken-docs - rev: 1.13.0 + rev: 1.16.0 hooks: - id: blacken-docs additional_dependencies: - - black==23.9.0 + - black==24.1.0 + files: 'docs/.*\.txt$' - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-eslint - rev: v8.49.0 + rev: v8.56.0 hooks: - id: eslint diff --git a/AUTHORS b/AUTHORS index b1f6c9578bb..e8a7cf19d4a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1082,6 +1082,6 @@ A big THANK YOU goes to: Ian Bicking for convincing Adrian to ditch code generation. - Mark Pilgrim for "Dive Into Python" (https://www.diveinto.org/python3/). + Mark Pilgrim for "Dive Into Python" (https://diveintopython3.net/). Guido van Rossum for creating Python. diff --git a/django/__init__.py b/django/__init__.py index 3b96a486eb0..9a527fd50d7 100644 --- a/django/__init__.py +++ b/django/__init__.py @@ -1,6 +1,6 @@ from django.utils.version import get_version -VERSION = (5, 0, 0, "final", 0) +VERSION = (5, 0, 2, "final", 0) __version__ = get_version(VERSION) diff --git a/django/__main__.py b/django/__main__.py index 8b96e91ea85..74151438482 100644 --- a/django/__main__.py +++ b/django/__main__.py @@ -3,6 +3,7 @@ Example: python -m django check """ + from django.core import management if __name__ == "__main__": diff --git a/django/conf/locale/af/LC_MESSAGES/django.mo b/django/conf/locale/af/LC_MESSAGES/django.mo index efb8b0fd9ec..8b37fdb3fb6 100644 Binary files a/django/conf/locale/af/LC_MESSAGES/django.mo and b/django/conf/locale/af/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/af/LC_MESSAGES/django.po b/django/conf/locale/af/LC_MESSAGES/django.po index 405b9f64818..cbd7abfedc4 100644 --- a/django/conf/locale/af/LC_MESSAGES/django.po +++ b/django/conf/locale/af/LC_MESSAGES/django.po @@ -358,15 +358,15 @@ msgstr "Gee ’n geldige e-posadres." msgid "" "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." msgstr "" -"Gee ’n geldige “slak” in wat bestaan ​​uit letters, syfers, onderstreep of " +"Gee ’n geldige “slak” wat bestaan ​​uit letters, syfers, onderstreep of " "koppelteken." msgid "" "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " "hyphens." msgstr "" -"Gee ’n geldige “slak” in wat bestaan ​​uit Unicode-letters, syfers, " -"onderstreep of koppelteken." +"Gee ’n geldige “slak” wat bestaan ​​uit Unicode-letters, syfers, onderstreep " +"of koppelteken." msgid "Enter a valid IPv4 address." msgstr "Gee ’n geldige IPv4-adres." @@ -846,6 +846,8 @@ msgid "" "%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " "may be ambiguous or it may not exist." msgstr "" +"%(datetime)s kon nie in die tydsone %(current_timezone)s vertolk word nie; " +"dit is dalk dubbelsinnig, of bestaan dalk nie." msgid "Clear" msgstr "Maak skoon" @@ -1186,12 +1188,19 @@ msgid "" "required for security reasons, to ensure that your browser is not being " "hijacked by third parties." msgstr "" +"U sien hierdie boodskap omdat dié HTTPS-werf vereis dat u webblaaier ’n " +"“Referer header” moet stuur, maar dit is nie gestuur nie. Hierdie header is " +"vir sekuriteitsredes nodig om te verseker dat u blaaier nie deur derde " +"partye gekaap is nie." msgid "" "If you have configured your browser to disable “Referer” headers, please re-" "enable them, at least for this site, or for HTTPS connections, or for “same-" "origin” requests." msgstr "" +"As “Referer headers” in u blaaier gedeaktiveer is, heraktiveer hulle asb. " +"ten minste vir dié werf, of vir HTTPS-verbindings, of vir “same-origin”-" +"versoeke." msgid "" "If you are using the tag or " @@ -1200,6 +1209,11 @@ msgid "" "If you’re concerned about privacy, use alternatives like for links to third-party sites." msgstr "" +"Indien u die -etiket gebruik " +"of die “Referrer-Policy: no-referrer” header gebruik, verwyder hulle asb. " +"Die CSRF-beskerming vereis die “Referer” header om streng kontrole van die " +"verwysende bladsy te doen. Indien u besorg is oor privaatheid, gebruik " +"alternatiewe soos vir skakels na derdepartywebwerwe." msgid "" "You are seeing this message because this site requires a CSRF cookie when " @@ -1214,6 +1228,8 @@ msgid "" "If you have configured your browser to disable cookies, please re-enable " "them, at least for this site, or for “same-origin” requests." msgstr "" +"Indien koekies in u blaaier gedeaktiveer is, aktiveerder hulle asb. ten " +"minste vir dié werf, of vir “same-origin”-versoeke." msgid "More information is available with DEBUG=True." msgstr "Meer inligting is beskikbaar met DEBUG=True." @@ -1255,6 +1271,7 @@ msgstr "Geen %(verbose_name)s gevind vir die soektog" msgid "Page is not “last”, nor can it be converted to an int." msgstr "" +"Bladsy is nie “last” nie, en dit kan nie omgeskakel word na ’n heelgetal nie." #, python-format msgid "Invalid page (%(page_number)s): %(message)s" @@ -1262,7 +1279,7 @@ msgstr "Ongeldige bladsy (%(page_number)s): %(message)s" #, python-format msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "" +msgstr "Leë lys en “%(class_name)s.allow_empty” is vals." msgid "Directory indexes are not allowed here." msgstr "Gidsindekse word nie hier toegelaat nie." diff --git a/django/conf/locale/ckb/LC_MESSAGES/django.mo b/django/conf/locale/ckb/LC_MESSAGES/django.mo index ca3d949bce5..cf41a447ecd 100644 Binary files a/django/conf/locale/ckb/LC_MESSAGES/django.mo and b/django/conf/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/ckb/LC_MESSAGES/django.po b/django/conf/locale/ckb/LC_MESSAGES/django.po index af7fef26d7f..0d78c77e4b9 100644 --- a/django/conf/locale/ckb/LC_MESSAGES/django.po +++ b/django/conf/locale/ckb/LC_MESSAGES/django.po @@ -5,14 +5,14 @@ # Bawar Jalal, 2020-2021 # Bawar Jalal, 2020 # kosar tofiq , 2020-2021 -# Swara , 2022-2023 +# Swara , 2022-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-17 02:13-0600\n" -"PO-Revision-Date: 2023-04-25 06:49+0000\n" -"Last-Translator: Swara , 2022-2023\n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-01-12 06:49+0000\n" +"Last-Translator: Swara , 2022-2024\n" "Language-Team: Central Kurdish (http://app.transifex.com/django/django/" "language/ckb/)\n" "MIME-Version: 1.0\n" @@ -55,7 +55,7 @@ msgid "Catalan" msgstr "کاتالانی" msgid "Central Kurdish (Sorani)" -msgstr "" +msgstr "کوردی" msgid "Czech" msgstr "چیکی" @@ -297,6 +297,9 @@ msgstr "تاتاری" msgid "Udmurt" msgstr "ئودمورتی" +msgid "Uyghur" +msgstr "ئۆیغور" + msgid "Ukrainian" msgstr "ئۆکرانی" @@ -393,6 +396,15 @@ msgstr "دڵنیاببە ئەم نرخە گەورەترە یاخود یەکسا msgid "Ensure this value is a multiple of step size %(limit_value)s." msgstr "دڵنیابە کە ئەم بەهایە چەندانێکە لە قەبارەی هەنگاوی%(limit_value)s." +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"دڵنیابە ئەم بەهایە چەند هێندەیەکی قەبارەی هەنگاوەکانە %(limit_value)s, " +"دەستپێدەکات لە %(offset)s، بۆ نموونە %(offset)s، %(valid_value1)s، " +"%(valid_value2)s، هتد." + #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " @@ -504,7 +516,7 @@ msgid "String (up to %(max_length)s)" msgstr "ڕیزبەند (تا %(max_length)s)" msgid "String (unlimited)" -msgstr "" +msgstr "ڕیز(بێسنوور)" msgid "Comma-separated integers" msgstr "ژمارە تەواوەکان بە کۆما جیاکراونەتەوە" diff --git a/django/conf/locale/es/LC_MESSAGES/django.mo b/django/conf/locale/es/LC_MESSAGES/django.mo index d95011b09bc..f84b5336745 100644 Binary files a/django/conf/locale/es/LC_MESSAGES/django.mo and b/django/conf/locale/es/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/es/LC_MESSAGES/django.po b/django/conf/locale/es/LC_MESSAGES/django.po index 1539ce87dfe..fa014d6660c 100644 --- a/django/conf/locale/es/LC_MESSAGES/django.po +++ b/django/conf/locale/es/LC_MESSAGES/django.po @@ -32,6 +32,7 @@ # Mariusz Felisiak , 2021 # mpachas , 2022 # monobotsoft , 2012 +# Natalia (Django Fellow), 2024 # ntrrgc , 2013 # ntrrgc , 2013 # Pablo, 2015 @@ -46,15 +47,16 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 06:49+0000\n" -"Last-Translator: Uriel Medina , 2020-2021,2023\n" +"PO-Revision-Date: 2024-01-12 06:49+0000\n" +"Last-Translator: Natalia (Django Fellow), 2024\n" "Language-Team: Spanish (http://app.transifex.com/django/django/language/" "es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? " +"1 : 2;\n" msgid "Afrikaans" msgstr "Africano" @@ -1203,7 +1205,7 @@ msgstr ", " #, python-format msgid "%(num)d year" msgid_plural "%(num)d years" -msgstr[0] "%(num)d años" +msgstr[0] "%(num)d año" msgstr[1] "%(num)d años" msgstr[2] "%(num)d años" @@ -1238,8 +1240,8 @@ msgstr[2] "%(num)d horas" #, python-format msgid "%(num)d minute" msgid_plural "%(num)d minutes" -msgstr[0] "%(num)d minutos" -msgstr[1] "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" msgstr[2] "%(num)d minutos" msgid "Forbidden" diff --git a/django/conf/locale/hu/LC_MESSAGES/django.mo b/django/conf/locale/hu/LC_MESSAGES/django.mo index 621965a6915..f55eb626b48 100644 Binary files a/django/conf/locale/hu/LC_MESSAGES/django.mo and b/django/conf/locale/hu/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/hu/LC_MESSAGES/django.po b/django/conf/locale/hu/LC_MESSAGES/django.po index 54dd7ef6cad..117789e33e3 100644 --- a/django/conf/locale/hu/LC_MESSAGES/django.po +++ b/django/conf/locale/hu/LC_MESSAGES/django.po @@ -4,6 +4,7 @@ # Akos Zsolt Hochrein , 2018 # András Veres-Szentkirályi, 2016-2021,2023 # Attila Nagy <>, 2012 +# Balázs Meskó , 2024 # Balázs R, 2023 # Dóra Szendrei , 2017 # Istvan Farkas , 2019 @@ -17,8 +18,8 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 06:49+0000\n" -"Last-Translator: András Veres-Szentkirályi, 2016-2021,2023\n" +"PO-Revision-Date: 2024-01-12 06:49+0000\n" +"Last-Translator: Balázs Meskó , 2024\n" "Language-Team: Hungarian (http://app.transifex.com/django/django/language/" "hu/)\n" "MIME-Version: 1.0\n" @@ -286,13 +287,13 @@ msgid "Telugu" msgstr "Telugu" msgid "Tajik" -msgstr "tadzsik" +msgstr "Tádzsik" msgid "Thai" msgstr "Thai" msgid "Turkmen" -msgstr "türkmén" +msgstr "Türkmén" msgid "Turkish" msgstr "Török" @@ -304,7 +305,7 @@ msgid "Udmurt" msgstr "Udmurt" msgid "Uyghur" -msgstr "ujgur" +msgstr "Ujgur" msgid "Ukrainian" msgstr "Ukrán" @@ -339,7 +340,7 @@ msgstr "Szindikáció" #. Translators: String used to replace omitted page numbers in elided page #. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. msgid "…" -msgstr "..." +msgstr "…" msgid "That page number is not an integer" msgstr "Az oldalszám nem egész szám." @@ -491,7 +492,7 @@ msgstr "Már létezik %(model_name)s ilyennel: %(field_labels)s." #, python-format msgid "Constraint “%(name)s” is violated." -msgstr "\"%(name)s\" kényszer megsértve." +msgstr "„%(name)s” megszorítás megsértve." #, python-format msgid "Value %(value)r is not a valid choice." diff --git a/django/conf/locale/mn/LC_MESSAGES/django.mo b/django/conf/locale/mn/LC_MESSAGES/django.mo index 06071c937ba..c35a525c44e 100644 Binary files a/django/conf/locale/mn/LC_MESSAGES/django.mo and b/django/conf/locale/mn/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/mn/LC_MESSAGES/django.po b/django/conf/locale/mn/LC_MESSAGES/django.po index d846523da56..47479f8f698 100644 --- a/django/conf/locale/mn/LC_MESSAGES/django.po +++ b/django/conf/locale/mn/LC_MESSAGES/django.po @@ -7,6 +7,7 @@ # Jannis Leidel , 2011 # jargalan , 2011 # Tsolmon , 2011 +# Turmunkh Batkhuyag, 2023 # Zorig, 2013-2014,2016,2018 # Zorig, 2019 # Анхбаяр Анхаа , 2013-2016,2018-2019 @@ -16,10 +17,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-27 22:40+0200\n" -"PO-Revision-Date: 2019-11-05 07:28+0000\n" -"Last-Translator: Анхбаяр Анхаа \n" -"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-25 06:49+0000\n" +"Last-Translator: Turmunkh Batkhuyag, 2023\n" +"Language-Team: Mongolian (http://app.transifex.com/django/django/language/" "mn/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -33,6 +34,9 @@ msgstr "Африк" msgid "Arabic" msgstr "Араб" +msgid "Algerian Arabic" +msgstr "Алжир Араб" + msgid "Asturian" msgstr "Астури" @@ -57,6 +61,9 @@ msgstr "Босни" msgid "Catalan" msgstr "Каталан" +msgid "Central Kurdish (Sorani)" +msgstr "Төв Курд (Сорани)" + msgid "Czech" msgstr "Чех" @@ -156,6 +163,9 @@ msgstr "Interlingua" msgid "Indonesian" msgstr "Индонези" +msgid "Igbo" +msgstr "Игбо" + msgid "Ido" msgstr "Идо" @@ -186,6 +196,9 @@ msgstr "Канад" msgid "Korean" msgstr "Солонгос" +msgid "Kyrgyz" +msgstr "Киргиз" + msgid "Luxembourgish" msgstr "Лүксенбүргиш" @@ -207,6 +220,9 @@ msgstr "Монгол" msgid "Marathi" msgstr "маратхи" +msgid "Malay" +msgstr "Малай" + msgid "Burmese" msgstr "Бирм" @@ -270,9 +286,15 @@ msgstr "Тамил" msgid "Telugu" msgstr "Тэлүгү" +msgid "Tajik" +msgstr "Тажик" + msgid "Thai" msgstr "Тайланд" +msgid "Turkmen" +msgstr "Турк хүн" + msgid "Turkish" msgstr "Турк" @@ -282,6 +304,9 @@ msgstr "Татар" msgid "Udmurt" msgstr "Удмурт" +msgid "Uyghur" +msgstr "Уйгур" + msgid "Ukrainian" msgstr "Украйн" @@ -312,6 +337,11 @@ msgstr "Статик файлууд" msgid "Syndication" msgstr "Нэгтгэл" +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + msgid "That page number is not an integer" msgstr "Хуудасны дугаар бүхэл тоо / Integer / биш байна" @@ -337,11 +367,15 @@ msgstr "Зөв имэйл хаяг оруулна уу" msgid "" "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." msgstr "" +"Үсэг, тоо, доогуур зураас эсвэл зурааснаас бүрдсэн хүчинтэй \"slug\" оруулна " +"уу." msgid "" "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " "hyphens." msgstr "" +"Юникод үсэг, тоо, доогуур зураас, зурааснаас бүрдсэн хүчинтэй \"slug\" " +"оруулна уу." msgid "Enter a valid IPv4 address." msgstr "Зөв IPv4 хаяг оруулна уу. " @@ -369,6 +403,20 @@ msgstr "Энэ утга %(limit_value)s -с бага эсвэл тэнцүү б msgid "Ensure this value is greater than or equal to %(limit_value)s." msgstr "Энэ утга %(limit_value)s -с их эсвэл тэнцүү байх нөхцлийг хангана уу." +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Утга нь алхамын хэмжээнд %(limit_value)s-ээс олон байхыг " +"баталгаажуулна уу." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Энэ утга нь алхмын хэмжээнд %(limit_value)s, %(offset)s-с эхлэн %(offset)s, " +"%(valid_value1)s, %(valid_value2)s гэх мэт утга байхыг баталгаажуулна уу." + #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " @@ -425,6 +473,8 @@ msgid "" "File extension “%(extension)s” is not allowed. Allowed extensions are: " "%(allowed_extensions)s." msgstr "" +"Файлын өргөтгөл “%(extension)s” зөвшөөрөгдөөгүй байна. Боломжит өргөтгөлүүд: " +"%(allowed_extensions)s." msgid "Null characters are not allowed." msgstr "Хоосон тэмдэгт зөвшөөрөгдөхгүй." @@ -436,6 +486,10 @@ msgstr "ба" msgid "%(model_name)s with this %(field_labels)s already exists." msgstr "%(field_labels)s талбар бүхий %(model_name)s аль хэдийн орсон байна." +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "“%(name)s” хязгаарлалтыг зөрчсөн." + #, python-format msgid "Value %(value)r is not a valid choice." msgstr "%(value)r буруу сонголт байна." @@ -450,8 +504,8 @@ msgstr "Энэ хэсэг хоосон байж болохгүй." msgid "%(model_name)s with this %(field_label)s already exists." msgstr "%(field_label)s-тэй %(model_name)s-ийг аль хэдийнэ оруулсан байна." -#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. -#. Eg: "Title must be unique for pub_date year" +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" #, python-format msgid "" "%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." @@ -465,11 +519,11 @@ msgstr "Талбарийн төрөл нь : %(field_type)s" #, python-format msgid "“%(value)s” value must be either True or False." -msgstr "" +msgstr "\"“%(value)s” утга True эсвэл False байх ёстой.\"" #, python-format msgid "“%(value)s” value must be either True, False, or None." -msgstr "" +msgstr "“%(value)s” утга True, False, эсвэл None байх ёстой." msgid "Boolean (Either True or False)" msgstr "Boolean (Үнэн худлын аль нэг нь)" @@ -478,6 +532,9 @@ msgstr "Boolean (Үнэн худлын аль нэг нь)" msgid "String (up to %(max_length)s)" msgstr "Бичвэр (%(max_length)s хүртэл)" +msgid "String (unlimited)" +msgstr "Тэмдэг мөр (хязгааргүй)" + msgid "Comma-separated integers" msgstr "Таслалаар тусгаарлагдсан бүхэл тоо" @@ -486,12 +543,15 @@ msgid "" "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " "format." msgstr "" +"“%(value)s” утга нь буруу огнооны форматтай байна. Энэ нь YYYY-MM-DD " +"форматтай байх ёстой." #, python-format msgid "" "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " "date." msgstr "" +"“%(value)s” утга зөв (YYYY-MM-DD) форматтай байна, гэхдээ буруу огноо байна." msgid "Date (without time)" msgstr "Огноо (цаггүй)" @@ -501,19 +561,23 @@ msgid "" "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." "uuuuuu]][TZ] format." msgstr "" +"“%(value)s” утга буруу форматтай байна. Энэ нь YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ] форматтай байх ёстой." #, python-format msgid "" "“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" "[TZ]) but it is an invalid date/time." msgstr "" +"“%(value)s” утгын формат зөв байна (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) " +"гэхдээ буруу огноо/цаг байна." msgid "Date (with time)" msgstr "Огноо (цагтай)" #, python-format msgid "“%(value)s” value must be a decimal number." -msgstr "" +msgstr "“%(value)s” утга нь бодит тоо байх ёстой." msgid "Decimal number" msgstr "Аравтын бутархайт тоо" @@ -523,6 +587,8 @@ msgid "" "“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." "uuuuuu] format." msgstr "" +"“%(value)s” утга буруу форматтай байна. Энэ нь [DD] [[HH:]MM:]ss[.uuuuuu] " +"форматтай байх ёстой." msgid "Duration" msgstr "Үргэлжлэх хугацаа" @@ -542,7 +608,7 @@ msgstr "Хөвөгч таслалтай тоо" #, python-format msgid "“%(value)s” value must be an integer." -msgstr "" +msgstr "“%(value)s” утга нь бүхэл тоо байх ёстой." msgid "Integer" msgstr "Бүхэл тоо" @@ -550,6 +616,9 @@ msgstr "Бүхэл тоо" msgid "Big (8 byte) integer" msgstr "Том (8 байт) бүхэл тоо" +msgid "Small integer" +msgstr "Бага тоон утна" + msgid "IPv4 address" msgstr "IPv4 хаяг" @@ -558,11 +627,14 @@ msgstr "IP хаяг" #, python-format msgid "“%(value)s” value must be either None, True or False." -msgstr "" +msgstr "\"“%(value)s” утга нь None, True эсвэл False байх ёстой.\"" msgid "Boolean (Either True, False or None)" msgstr "Boolean (Үнэн, худал, эсвэл юу ч биш)" +msgid "Positive big integer" +msgstr "Эерэг том бүхэл тоо" + msgid "Positive integer" msgstr "Бүхэл тоох утга" @@ -573,9 +645,6 @@ msgstr "Бага бүхэл тоон утга" msgid "Slug (up to %(max_length)s)" msgstr "Слаг (ихдээ %(max_length)s )" -msgid "Small integer" -msgstr "Бага тоон утна" - msgid "Text" msgstr "Текст" @@ -584,12 +653,16 @@ msgid "" "“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " "format." msgstr "" +"“%(value)s” утга буруу форматтай байна. Энэ нь HH:MM[:ss[.uuuuuu]] форматтай " +"байх ёстой." #, python-format msgid "" "“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " "invalid time." msgstr "" +"“%(value)s” утга зөв форматтай байна (HH:MM[:ss[.uuuuuu]]) гэхдээ буруу цаг " +"байна." msgid "Time" msgstr "Цаг" @@ -602,7 +675,7 @@ msgstr "Бинари өгөгдөл" #, python-format msgid "“%(value)s” is not a valid UUID." -msgstr "" +msgstr "“%(value)s” нь хүчинтэй UUID биш." msgid "Universally unique identifier" msgstr "UUID" @@ -613,6 +686,12 @@ msgstr "Файл" msgid "Image" msgstr "Зураг" +msgid "A JSON object" +msgstr "JSON объект " + +msgid "Value must be valid JSON." +msgstr "JSON утга байх боломжтой." + #, python-format msgid "%(model)s instance with %(field)s %(value)r does not exist." msgstr "%(field)s %(value)r утгатай %(model)s байхгүй байна." @@ -705,6 +784,9 @@ msgstr "Бүрэн утга оруулна уу." msgid "Enter a valid UUID." msgstr "Зөв UUID оруулна уу." +msgid "Enter a valid JSON." +msgstr "JSON-ийн бүтцээр оруулна уу." + #. Translators: This is the default suffix added to form field labels msgid ":" msgstr ":" @@ -713,20 +795,26 @@ msgstr ":" msgid "(Hidden field %(name)s) %(error)s" msgstr "(Нууц талбар%(name)s) %(error)s" -msgid "ManagementForm data is missing or has been tampered with" -msgstr "УдирдахФормын мэдээлэл олдсонгүй эсвэл өөрчлөгдсөн байна" +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm-ын өгөгдөл дутуу эсвэл өөрчилсөн байна. Дутуу талбарууд: " +"%(field_names)s. Хэрэв асуудал хэвээр байвал та алдааны тайлан гаргах " +"шаардлагатай байж магадгүй." #, python-format -msgid "Please submit %d or fewer forms." -msgid_plural "Please submit %d or fewer forms." -msgstr[0] "%d ихгүй форм илгээн үү" -msgstr[1] "%d ихгүй форм илгээн үү" +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Та хамгийн ихдээ %(num)d форм илгээнэ үү." +msgstr[1] "Та хамгийн ихдээ %(num)d форм илгээнэ үү." #, python-format -msgid "Please submit %d or more forms." -msgid_plural "Please submit %d or more forms." -msgstr[0] "%d эсвэл их форм илгээнэ үү" -msgstr[1] "%d эсвэл их форм илгээнэ үү" +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Та хамгийн багадаа %(num)d форм илгээнэ үү." +msgstr[1] "Та хамгийн багадаа %(num)d форм илгээнэ үү." msgid "Order" msgstr "Эрэмбэлэх" @@ -763,13 +851,15 @@ msgstr "Зөв сонголт хийнэ үү. Энэ утга сонголто #, python-format msgid "“%(pk)s” is not a valid value." -msgstr "" +msgstr "“%(pk)s” нь шаардлага хангаагүй утга байна." #, python-format msgid "" "%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " "may be ambiguous or it may not exist." msgstr "" +"%(datetime)s нь %(current_timezone)s цагийн бүсэд хөрвүүлэх боломжгүй байна; " +"энэ нь хоёрдмол утгатай эсвэл байхгүй байж болно." msgid "Clear" msgstr "Цэвэрлэх" @@ -789,15 +879,7 @@ msgstr "Тийм" msgid "No" msgstr "Үгүй" -msgid "Year" -msgstr "Жил" - -msgid "Month" -msgstr "Сар" - -msgid "Day" -msgstr "Өдөр" - +#. Translators: Please do not add spaces around commas. msgid "yes,no,maybe" msgstr "тийм,үгүй,магадгүй" @@ -1071,43 +1153,40 @@ msgid ", " msgstr ", " #, python-format -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "%d жил" -msgstr[1] "%d жил" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d жил" +msgstr[1] "%(num)d жил" #, python-format -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "%d сар" -msgstr[1] "%d сар" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d сар" +msgstr[1] "%(num)d сар" #, python-format -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "%d долоо хоног" -msgstr[1] "%d долоо хоног" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d долоо хоног" +msgstr[1] "%(num)d долоо хоног" #, python-format -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "%d өдөр" -msgstr[1] "%d өдөр" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d өдөр" +msgstr[1] "%(num)d өдөр" #, python-format -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "%d цаг" -msgstr[1] "%d цаг" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d цаг" +msgstr[1] "%(num)d цаг" #, python-format -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "%d минут" -msgstr[1] "%d минут" - -msgid "0 minutes" -msgstr "0 минут" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минут" +msgstr[1] "%(num)d минут" msgid "Forbidden" msgstr "Хориотой" @@ -1117,24 +1196,34 @@ msgstr "CSRF дээр уналаа. Хүсэлт таслагдсан." msgid "" "You are seeing this message because this HTTPS site requires a “Referer " -"header” to be sent by your Web browser, but none was sent. This header is " +"header” to be sent by your web browser, but none was sent. This header is " "required for security reasons, to ensure that your browser is not being " "hijacked by third parties." msgstr "" +"Та энэ мэдэгдлийг харж байгаа нь таны веб хөтөчөөс 'Referer header'-ийг " +"HTTPS хуудасд илгээх шаардлагатай байгаатай холбоотой. Энэ нь гуравдагч " +"этгээдээс хамгаалахын тулд шаардлагатай." msgid "" "If you have configured your browser to disable “Referer” headers, please re-" "enable them, at least for this site, or for HTTPS connections, or for “same-" "origin” requests." msgstr "" +"Хэрвээ та веб хөтөчөө 'Referer' толгойг идэвхигүй болгосон бол энэ хуудас, " +"HTTPS холболт эсвэл 'same-origin' хүсэлтэнд зориулж идэвхижүүлнэ үү." msgid "" "If you are using the tag or " "including the “Referrer-Policy: no-referrer” header, please remove them. The " "CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." +"If you’re concerned about privacy, use alternatives like for links to third-party sites." msgstr "" +"Хэрвээ та таг ашиглаж " +"байгаа бол эсвэл 'Referrer-Policy: no-referrer' толгойг нэмсэн бол, " +"эдгээрийг устгана уу. CSRF хамгаалалт 'Referer' толгойг чанд шалгалт хийхийг " +"шаарддаг. Хэрвээ та аюулгүй байдлыг чухалчилж байгаа бол гуравдагч сайтыг " +"холбохдоо ашиглана уу." msgid "" "You are seeing this message because this site requires a CSRF cookie when " @@ -1149,6 +1238,8 @@ msgid "" "If you have configured your browser to disable cookies, please re-enable " "them, at least for this site, or for “same-origin” requests." msgstr "" +"Хэрвээ та веб хөтөчийн \"cookies\"-г хаасан бол энэ хуудас эсвэл 'same-" +"origin' хүсэлтэнд зориулж идэвхижүүлнэ үү." msgid "More information is available with DEBUG=True." msgstr "DEBUG=True үед дэлгэрэнгүй мэдээлэл харах боломжтой." @@ -1183,13 +1274,14 @@ msgstr "" #, python-format msgid "Invalid date string “%(datestr)s” given format “%(format)s”" msgstr "" +"Буруу огноо. '%(datestr)s' огноо '%(format)s' хэлбэрт тохирохгүй байна." #, python-format msgid "No %(verbose_name)s found matching the query" msgstr "Шүүлтүүрт таарах %(verbose_name)s олдсонгүй " msgid "Page is not “last”, nor can it be converted to an int." -msgstr "" +msgstr "Хуудас \"сүүлчийн\" биш бөгөөд үүнийг int болгон хувиргах боломжгүй." #, python-format msgid "Invalid page (%(page_number)s): %(message)s" @@ -1197,7 +1289,7 @@ msgstr "Буруу хуудас (%(page_number)s): %(message)s" #, python-format msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "" +msgstr "Хоосон жагсаалт ба “%(class_name)s.allow_empty” нь False байна." msgid "Directory indexes are not allowed here." msgstr "Файлын жагсаалтыг энд зөвшөөрөөгүй." @@ -1210,8 +1302,8 @@ msgstr "“%(path)s” хуудас байхгүй байна." msgid "Index of %(directory)s" msgstr "%(directory)s ийн жагсаалт" -msgid "Django: the Web framework for perfectionists with deadlines." -msgstr "Джанго: Чанартай бөгөөд хугацаанд нь хийхэд зориулсан Web framework." +msgid "The install worked successfully! Congratulations!" +msgstr "Амжилттай суулгалаа! Баяр хүргэе!" #, python-format msgid "" @@ -1222,26 +1314,23 @@ msgstr "" "%(version)s/releases/\" target=\"_blank\" rel=\"noopener\">тэмдэглэл харах " -msgid "The install worked successfully! Congratulations!" -msgstr "Амжилттай суулгалаа! Баяр хүргэе!" - #, python-format msgid "" "You are seeing this page because DEBUG=True is in your settings file and you have not configured any " -"URLs." +"%(version)s/ref/settings/#debug\" target=\"_blank\" " +"rel=\"noopener\">DEBUG=True is in your settings file and you have not " +"configured any URLs." msgstr "" "Таний тохиргооны файл дээр DEBUG=TRUE гэж тохируулсан мөн URLs дээр тохиргоо хийгээгүй учраас " -"энэ хуудасыг харж байна." +"%(version)s/ref/settings/#debug\" target=\"_blank\" " +"rel=\"noopener\">DEBUG=TRUE гэж тохируулсан мөн URLs дээр тохиргоо " +"хийгээгүй учраас энэ хуудасыг харж байна." msgid "Django Documentation" msgstr "Джанго баримтжуулалт" msgid "Topics, references, & how-to’s" -msgstr "" +msgstr "Сэдэв, лавлахууд болон зааврууд" msgid "Tutorial: A Polling App" msgstr "Хичээл: Санал асуулга App" diff --git a/django/conf/locale/mr/LC_MESSAGES/django.mo b/django/conf/locale/mr/LC_MESSAGES/django.mo index 46c9f342103..8cf9a708eac 100644 Binary files a/django/conf/locale/mr/LC_MESSAGES/django.mo and b/django/conf/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/mr/LC_MESSAGES/django.po b/django/conf/locale/mr/LC_MESSAGES/django.po index ab6908514f9..fe4c6ebb2b8 100644 --- a/django/conf/locale/mr/LC_MESSAGES/django.po +++ b/django/conf/locale/mr/LC_MESSAGES/django.po @@ -1,15 +1,16 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 # Suraj Kawade, 2013 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-27 22:40+0200\n" -"PO-Revision-Date: 2019-11-05 00:38+0000\n" -"Last-Translator: Ramiro Morales\n" -"Language-Team: Marathi (http://www.transifex.com/django/django/language/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-01-20 06:49+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -23,8 +24,11 @@ msgstr "अफ्रिकान्स" msgid "Arabic" msgstr "अरेबिक" +msgid "Algerian Arabic" +msgstr "अल्जेरियन अरेबिक" + msgid "Asturian" -msgstr "" +msgstr "अस्टूरियन" msgid "Azerbaijani" msgstr "अझरबैजानी" @@ -33,7 +37,7 @@ msgid "Bulgarian" msgstr "बल्गेरियन" msgid "Belarusian" -msgstr "बेलारूसी" +msgstr "बेलारशियन" msgid "Bengali" msgstr "बंगाली" @@ -47,6 +51,9 @@ msgstr "बोस्नियन" msgid "Catalan" msgstr "कॅटलान" +msgid "Central Kurdish (Sorani)" +msgstr "मध्य कुर्दिश (सोरानी)" + msgid "Czech" msgstr "झेक" @@ -60,7 +67,7 @@ msgid "German" msgstr "जर्मन" msgid "Lower Sorbian" -msgstr "" +msgstr "लोअर सोर्बियन" msgid "Greek" msgstr "ग्रीक" @@ -69,7 +76,7 @@ msgid "English" msgstr "इंग्रजी" msgid "Australian English" -msgstr "" +msgstr "ऑस्ट्रेलियन इंग्रजी" msgid "British English" msgstr "ब्रिटिश इंग्रजी" @@ -84,277 +91,310 @@ msgid "Argentinian Spanish" msgstr "अर्जेन्टिनाची स्पॅनिश" msgid "Colombian Spanish" -msgstr "" +msgstr "कोलंबियन स्पॅनिश" msgid "Mexican Spanish" msgstr "मेक्सिकन स्पॅनिश" msgid "Nicaraguan Spanish" -msgstr "" +msgstr "निकारागुआन स्पॅनिश" msgid "Venezuelan Spanish" -msgstr "" +msgstr "व्हेनेझुएलन स्पॅनिश" msgid "Estonian" -msgstr "" +msgstr "एस्टोनियन" msgid "Basque" -msgstr "" +msgstr "बास्क" msgid "Persian" -msgstr "" +msgstr "पर्शियन" msgid "Finnish" -msgstr "" +msgstr "फिनिश" msgid "French" -msgstr "" +msgstr "फ्रेंच" msgid "Frisian" -msgstr "" +msgstr "फ्रिसियन" msgid "Irish" -msgstr "" +msgstr "आयरिश" msgid "Scottish Gaelic" -msgstr "" +msgstr "स्कॉटिश गेलिक" msgid "Galician" -msgstr "" +msgstr "गॅलिशियन" msgid "Hebrew" -msgstr "" +msgstr "हिब्रू" msgid "Hindi" -msgstr "" +msgstr "हिंदी" msgid "Croatian" -msgstr "" +msgstr "क्रोएशियन" msgid "Upper Sorbian" -msgstr "" +msgstr "अप्पर सोर्बियन" msgid "Hungarian" -msgstr "" +msgstr "हंगेरियन" msgid "Armenian" -msgstr "" +msgstr "अर्मेनियन" msgid "Interlingua" -msgstr "" +msgstr "इंटरलिंगुआ" msgid "Indonesian" -msgstr "" +msgstr "इंडोनेशियन" + +msgid "Igbo" +msgstr "इग्बो" msgid "Ido" -msgstr "" +msgstr "इदो" msgid "Icelandic" -msgstr "" +msgstr "आयलँडिक" msgid "Italian" -msgstr "" +msgstr "इटालियन" msgid "Japanese" -msgstr "" +msgstr "जपानी" msgid "Georgian" -msgstr "" +msgstr "जॉर्जियन" msgid "Kabyle" -msgstr "" +msgstr "कबायल" msgid "Kazakh" -msgstr "" +msgstr "कझाक" msgid "Khmer" -msgstr "" +msgstr "ख्मेर" msgid "Kannada" -msgstr "" +msgstr "कन्नड" msgid "Korean" -msgstr "" +msgstr "कोरियन" + +msgid "Kyrgyz" +msgstr "किर्गिझ" msgid "Luxembourgish" -msgstr "" +msgstr "लक्झेंबर्गिश" msgid "Lithuanian" -msgstr "" +msgstr "लिथुआनियन" msgid "Latvian" -msgstr "" +msgstr "लाटव्हिअन" msgid "Macedonian" -msgstr "" +msgstr "मॅसेडोनिअन" msgid "Malayalam" -msgstr "" +msgstr "मल्याळम" msgid "Mongolian" -msgstr "" +msgstr "मंगोलियन" msgid "Marathi" -msgstr "" +msgstr "मराठी" + +msgid "Malay" +msgstr "मलय" msgid "Burmese" -msgstr "" +msgstr "बर्मीस" msgid "Norwegian Bokmål" -msgstr "" +msgstr "नॉर्वेजियन बोकमाल" msgid "Nepali" -msgstr "" +msgstr "नेपाळी" msgid "Dutch" -msgstr "" +msgstr "डच" msgid "Norwegian Nynorsk" -msgstr "" +msgstr "नॉर्वेजिअन निनॉर्स्क " msgid "Ossetic" -msgstr "" +msgstr "ओस्सेटिक" msgid "Punjabi" -msgstr "" +msgstr "पंजाबी" msgid "Polish" -msgstr "" +msgstr "पॉलिश" msgid "Portuguese" -msgstr "" +msgstr "पोर्तुगीज" msgid "Brazilian Portuguese" -msgstr "" +msgstr "ब्रझिलियन पोर्तुगीज" msgid "Romanian" -msgstr "" +msgstr "रोमेनियन" msgid "Russian" -msgstr "" +msgstr "रशियन" msgid "Slovak" -msgstr "" +msgstr "स्लोवाक" msgid "Slovenian" -msgstr "" +msgstr "स्लोवेनियन" msgid "Albanian" -msgstr "" +msgstr "अल्बेनियन" msgid "Serbian" -msgstr "" +msgstr "सर्बियन" msgid "Serbian Latin" -msgstr "" +msgstr "सर्बियन लॅटिन" msgid "Swedish" -msgstr "" +msgstr "स्वीडिश" msgid "Swahili" -msgstr "" +msgstr "स्वाहिली" msgid "Tamil" -msgstr "" +msgstr "तमिळ" msgid "Telugu" -msgstr "" +msgstr "तेलुगु" + +msgid "Tajik" +msgstr "ताजिक" msgid "Thai" -msgstr "" +msgstr "थाई" + +msgid "Turkmen" +msgstr "तुर्कमेन" msgid "Turkish" -msgstr "" +msgstr "तुर्की" msgid "Tatar" -msgstr "" +msgstr "टाटर" msgid "Udmurt" -msgstr "" +msgstr "उदमर्त" + +msgid "Uyghur" +msgstr "उईघुर" msgid "Ukrainian" -msgstr "" +msgstr "युक्रेनियन" msgid "Urdu" -msgstr "" +msgstr "उर्दू" msgid "Uzbek" -msgstr "" +msgstr "उझबेक" msgid "Vietnamese" -msgstr "" +msgstr "व्हिएतनामी" msgid "Simplified Chinese" -msgstr "" +msgstr "सोपी चायनिज" msgid "Traditional Chinese" -msgstr "" +msgstr "पारंपारिक चायनिज" msgid "Messages" -msgstr "" +msgstr "संदेश" msgid "Site Maps" -msgstr "" +msgstr "संकेतस्थळ नकाशे" msgid "Static Files" -msgstr "" +msgstr "स्थिर फाइल्स" msgid "Syndication" -msgstr "" +msgstr "सिंडिकेशन" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." msgid "That page number is not an integer" -msgstr "" +msgstr "तो पान क्रमांक पूर्णांक नाही." msgid "That page number is less than 1" -msgstr "" +msgstr "तो पान क्रमांक 1 पेक्षा कमी आहे" msgid "That page contains no results" -msgstr "" +msgstr "त्या पानावर कोणतेही परिणाम नाहीत." msgid "Enter a valid value." -msgstr "" +msgstr "वैध मूल्य टाका." msgid "Enter a valid URL." -msgstr "" +msgstr "एक योग्य युआरएल टाका करा." msgid "Enter a valid integer." -msgstr "" +msgstr "योग्य पूर्णांक टाका." msgid "Enter a valid email address." -msgstr "" +msgstr "योग्य विपत्र पत्ता टाका." #. Translators: "letters" means latin letters: a-z and A-Z. msgid "" "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." -msgstr "" +msgstr "अक्षरे, संख्या, अंडरस्कोर किंवा हायफनसह असलेला योग्य \"स्लग\" टाका." msgid "" "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " "hyphens." -msgstr "" +msgstr "योग्य \"स्लग\" टाका ज्यामध्ये यूनिकोड अक्षरे, अंक, अंडरस्कोर किंवा हायफन असतात." msgid "Enter a valid IPv4 address." -msgstr "" +msgstr "योग्य IPv4 पत्ता टाका." msgid "Enter a valid IPv6 address." -msgstr "" +msgstr "योग्य IPv6 पत्ता टाका." msgid "Enter a valid IPv4 or IPv6 address." -msgstr "" +msgstr "योग्य IPv4 किंवा IPv6 पत्ता नमूद करा." msgid "Enter only digits separated by commas." -msgstr "" +msgstr "स्वल्पविरामाने वेगळे केलेले अंकच फक्त नमूद करा." #, python-format msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." -msgstr "" +msgstr "हे मूल्य%(limit_value)s(%(show_value)s) आहे याची खात्री करा." #, python-format msgid "Ensure this value is less than or equal to %(limit_value)s." -msgstr "" +msgstr "हे मूल्य %(limit_value)sया मर्यादेइतके किंवा त्यापेक्षा कमी आहे याची काळजी घ्या." #, python-format msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "हे मूल्य %(limit_value)sया मर्यादेइतके किंवा त्यापेक्षा जास्त आहे याची काळजी घ्या." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "हे मूल्य पायरी आकार %(limit_value)s चा गुणाकार असल्याची खात्री करा." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." msgstr "" #, python-format @@ -378,7 +418,7 @@ msgstr[0] "" msgstr[1] "" msgid "Enter a number." -msgstr "" +msgstr "अंक टाका." #, python-format msgid "Ensure that there are no more than %(max)s digit in total." @@ -407,31 +447,35 @@ msgid "" msgstr "" msgid "Null characters are not allowed." -msgstr "" +msgstr "शून्य वर्णांना परवानगी नाही." msgid "and" -msgstr "" +msgstr "आणि" #, python-format msgid "%(model_name)s with this %(field_labels)s already exists." -msgstr "" +msgstr "%(model_name)s सह %(field_labels)s हे अगोदरच अस्तित्वात आहे." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "\"%(name)s\" च्या मर्यादेचं उल्लंघन आहे." #, python-format msgid "Value %(value)r is not a valid choice." -msgstr "" +msgstr "Value %(value)r हा योग्य पर्याय नाही." msgid "This field cannot be null." -msgstr "" +msgstr "हे क्षेत्र रिक्त असू शकत नाही." msgid "This field cannot be blank." -msgstr "" +msgstr "हे क्षेत्र रिक्त असू शकत नाही." #, python-format msgid "%(model_name)s with this %(field_label)s already exists." -msgstr "" +msgstr "%(model_name)s %(field_label)s ने अगोदरच अस्तित्वात आहे." -#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. -#. Eg: "Title must be unique for pub_date year" +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" #, python-format msgid "" "%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." @@ -439,26 +483,29 @@ msgstr "" #, python-format msgid "Field of type: %(field_type)s" -msgstr "" +msgstr "क्षेत्राचा प्रकार: %(field_type)s" #, python-format msgid "“%(value)s” value must be either True or False." -msgstr "" +msgstr "“%(value)s” मूल्य सत्य किंवा असत्य असावा." #, python-format msgid "“%(value)s” value must be either True, False, or None." -msgstr "" +msgstr "“%(value)s” मूल्य सत्य, असत्य किंवा कोणतेही नसावेत." msgid "Boolean (Either True or False)" -msgstr "" +msgstr "बूलियन (सत्य किंवा असत्य)" #, python-format msgid "String (up to %(max_length)s)" msgstr "" -msgid "Comma-separated integers" +msgid "String (unlimited)" msgstr "" +msgid "Comma-separated integers" +msgstr "स्वल्पविरामाने वेगळे केलेले पूर्णांक" + #, python-format msgid "" "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " @@ -472,7 +519,7 @@ msgid "" msgstr "" msgid "Date (without time)" -msgstr "" +msgstr "दिनांक (वेळेशिवाय)" #, python-format msgid "" @@ -487,7 +534,7 @@ msgid "" msgstr "" msgid "Date (with time)" -msgstr "" +msgstr "दिनांक (वेळेसह)" #, python-format msgid "“%(value)s” value must be a decimal number." @@ -503,13 +550,13 @@ msgid "" msgstr "" msgid "Duration" -msgstr "" +msgstr "कालावधी" msgid "Email address" -msgstr "" +msgstr "विपत्र पत्ता" msgid "File path" -msgstr "" +msgstr "दस्तऐवज मार्ग" #, python-format msgid "“%(value)s” value must be a float." @@ -523,39 +570,42 @@ msgid "“%(value)s” value must be an integer." msgstr "" msgid "Integer" -msgstr "" +msgstr "पूर्णांक" msgid "Big (8 byte) integer" msgstr "" +msgid "Small integer" +msgstr "लहान पूर्णांक" + msgid "IPv4 address" -msgstr "" +msgstr "IPv4 पत्ता" msgid "IP address" -msgstr "" +msgstr "IP पत्ता" #, python-format msgid "“%(value)s” value must be either None, True or False." msgstr "" msgid "Boolean (Either True, False or None)" -msgstr "" +msgstr "बुलियन (एकतर खरे, असत्य किंवा काहीही नाही)" + +msgid "Positive big integer" +msgstr "सकारात्मक मोठा पूर्णांक" msgid "Positive integer" -msgstr "" +msgstr "सकारात्मक पूर्णांक" msgid "Positive small integer" -msgstr "" +msgstr "सकारात्मक लहान पूर्णांक" #, python-format msgid "Slug (up to %(max_length)s)" msgstr "" -msgid "Small integer" -msgstr "" - msgid "Text" -msgstr "" +msgstr "मजकूर" #, python-format msgid "" @@ -570,27 +620,33 @@ msgid "" msgstr "" msgid "Time" -msgstr "" +msgstr "वेळ" msgid "URL" msgstr "" msgid "Raw binary data" -msgstr "" +msgstr "कच्चा बायनरी डेटा" #, python-format msgid "“%(value)s” is not a valid UUID." msgstr "" msgid "Universally unique identifier" -msgstr "" +msgstr "सार्वत्रिक अद्वितीय ओळखकर्ता" msgid "File" -msgstr "" +msgstr "फाइल" msgid "Image" +msgstr "चित्र " + +msgid "A JSON object" msgstr "" +msgid "Value must be valid JSON." +msgstr "मूल्य योग्य JSON असणे आवश्यक." + #, python-format msgid "%(model)s instance with %(field)s %(value)r does not exist." msgstr "" @@ -619,35 +675,35 @@ msgid ":?.!" msgstr ":?.!" msgid "This field is required." -msgstr "" +msgstr "हे क्षेत्र आवश्यक आहे." msgid "Enter a whole number." -msgstr "" +msgstr "पूर्ण संख्या प्रविष्ट करा." msgid "Enter a valid date." -msgstr "" +msgstr "योग्य दिनांक नमूद करा." msgid "Enter a valid time." -msgstr "" +msgstr "योग्य वेळ नमूद करा." msgid "Enter a valid date/time." -msgstr "" +msgstr "योग्य दिनांक/वेळ नमूद करा." msgid "Enter a valid duration." -msgstr "" +msgstr "योग्य कालावधी नमूद करा." #, python-brace-format msgid "The number of days must be between {min_days} and {max_days}." -msgstr "" +msgstr "दिवसांची संख्या {min_days} आणि {max_days} च्या मधे असावी." msgid "No file was submitted. Check the encoding type on the form." -msgstr "" +msgstr "कोणताही दस्तऐवज सुपूर्त केलेला नाही. अर्जावरील एन्कोडिंग प्रकार तपासा." msgid "No file was submitted." -msgstr "" +msgstr "कोणताही दस्तऐवज सुपूर्त केलेला नाही." msgid "The submitted file is empty." -msgstr "" +msgstr "सुपूर्त केलेला दस्तऐवज रिकामी आहे." #, python-format msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." @@ -657,25 +713,28 @@ msgstr[0] "" msgstr[1] "" msgid "Please either submit a file or check the clear checkbox, not both." -msgstr "" +msgstr "कृपया एकतर फाइल सबमिट करा किंवा स्पष्ट चेकबॉक्स चेक करा, दोन्ही नाही." msgid "" "Upload a valid image. The file you uploaded was either not an image or a " "corrupted image." -msgstr "" +msgstr "एक वैध प्रतिमा अपलोड करा. तुम्ही अपलोड केलेली फाइल चित्र किंवा दूषित चित्र नव्हते." #, python-format msgid "Select a valid choice. %(value)s is not one of the available choices." msgstr "" msgid "Enter a list of values." -msgstr "" +msgstr "मूल्यांची यादी नमूद करा." msgid "Enter a complete value." -msgstr "" +msgstr "पूर्ण मूल्य नमूद करा." msgid "Enter a valid UUID." -msgstr "" +msgstr "योग्य UUID नमूद करा." + +msgid "Enter a valid JSON." +msgstr "योग्य JSON नमूद करा." #. Translators: This is the default suffix added to form field labels msgid ":" @@ -685,30 +744,33 @@ msgstr ":" msgid "(Hidden field %(name)s) %(error)s" msgstr "" -msgid "ManagementForm data is missing or has been tampered with" +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." msgstr "" #, python-format -msgid "Please submit %d or fewer forms." -msgid_plural "Please submit %d or fewer forms." +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." msgstr[0] "" msgstr[1] "" #, python-format -msgid "Please submit %d or more forms." -msgid_plural "Please submit %d or more forms." +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." msgstr[0] "" msgstr[1] "" msgid "Order" -msgstr "" +msgstr "क्रम" msgid "Delete" -msgstr "" +msgstr "घालवा" #, python-format msgid "Please correct the duplicate data for %(field)s." -msgstr "" +msgstr "कृपया %(field)s साठी दुय्यम माहिती प्रत सुधारा." #, python-format msgid "Please correct the duplicate data for %(field)s, which must be unique." @@ -721,17 +783,17 @@ msgid "" msgstr "" msgid "Please correct the duplicate values below." -msgstr "" +msgstr "कृपया खालील नकली मूल्ये सुधारा." msgid "The inline value did not match the parent instance." -msgstr "" +msgstr "इनलाइन मूल्य मूळ उदाहरणाशी जुळत नाही." msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "" +msgstr "तो पर्याय उपलब्ध पर्यायांपैकी एक नाही. योग्य पर्याय निवडा. " #, python-format msgid "“%(pk)s” is not a valid value." -msgstr "" +msgstr "“%(pk)s” हे वैध मूल्य नाही." #, python-format msgid "" @@ -740,34 +802,26 @@ msgid "" msgstr "" msgid "Clear" -msgstr "" +msgstr "साफ करा" msgid "Currently" -msgstr "" +msgstr "सध्या" msgid "Change" -msgstr "" +msgstr "बदला" msgid "Unknown" -msgstr "" +msgstr "अज्ञात" msgid "Yes" -msgstr "" +msgstr "होय" msgid "No" -msgstr "" - -msgid "Year" -msgstr "" - -msgid "Month" -msgstr "" - -msgid "Day" -msgstr "" +msgstr "नाही" +#. Translators: Please do not add spaces around commas. msgid "yes,no,maybe" -msgstr "" +msgstr "होय,नाही,कदाचित" #, python-format msgid "%(size)d byte" @@ -777,254 +831,254 @@ msgstr[1] "" #, python-format msgid "%s KB" -msgstr "" +msgstr "%s केबी" #, python-format msgid "%s MB" -msgstr "" +msgstr "%s एमबी" #, python-format msgid "%s GB" -msgstr "" +msgstr "%s जीबी" #, python-format msgid "%s TB" -msgstr "" +msgstr "%s टिबी" #, python-format msgid "%s PB" -msgstr "" +msgstr "%s पीबी" msgid "p.m." -msgstr "" +msgstr "म.उ." msgid "a.m." -msgstr "" +msgstr "म.पू." msgid "PM" -msgstr "" +msgstr "मउ" msgid "AM" -msgstr "" +msgstr "मपू" msgid "midnight" -msgstr "" +msgstr "मध्यरात्री" msgid "noon" -msgstr "" +msgstr "दुपारी" msgid "Monday" -msgstr "" +msgstr "सोमवार" msgid "Tuesday" -msgstr "" +msgstr "मंगळवार" msgid "Wednesday" -msgstr "" +msgstr "बुधवार" msgid "Thursday" -msgstr "" +msgstr "गुरुवार" msgid "Friday" -msgstr "" +msgstr "शुक्रवार" msgid "Saturday" -msgstr "" +msgstr "शनिवार" msgid "Sunday" -msgstr "" +msgstr "रविवार" msgid "Mon" -msgstr "" +msgstr "सोम" msgid "Tue" -msgstr "" +msgstr "मंगळ" msgid "Wed" -msgstr "" +msgstr "बुध" msgid "Thu" -msgstr "" +msgstr "गुरु" msgid "Fri" -msgstr "" +msgstr "शुक्र" msgid "Sat" -msgstr "" +msgstr "शनि" msgid "Sun" -msgstr "" +msgstr "रवि" msgid "January" -msgstr "" +msgstr "जानेवारी" msgid "February" -msgstr "" +msgstr "फेब्रुवारी" msgid "March" -msgstr "" +msgstr "मार्च" msgid "April" -msgstr "" +msgstr "एप्रिल" msgid "May" -msgstr "" +msgstr "मे" msgid "June" -msgstr "" +msgstr "जून" msgid "July" -msgstr "" +msgstr "जुलै" msgid "August" -msgstr "" +msgstr "ऑगस्ट" msgid "September" -msgstr "" +msgstr "सप्टेंबर" msgid "October" -msgstr "" +msgstr "ऑक्टोबर" msgid "November" -msgstr "" +msgstr "नोव्हेंबर" msgid "December" -msgstr "" +msgstr "डिसेंबर" msgid "jan" -msgstr "" +msgstr "जान" msgid "feb" -msgstr "" +msgstr "फेब" msgid "mar" -msgstr "" +msgstr "मार" msgid "apr" -msgstr "" +msgstr "एप्रि" msgid "may" -msgstr "" +msgstr "मे" msgid "jun" -msgstr "" +msgstr "जून" msgid "jul" -msgstr "" +msgstr "जुल" msgid "aug" -msgstr "" +msgstr "ऑग" msgid "sep" -msgstr "" +msgstr "सप" msgid "oct" -msgstr "" +msgstr "ऑक्ट" msgid "nov" -msgstr "" +msgstr "नोव्ह" msgid "dec" -msgstr "" +msgstr "डिस" msgctxt "abbrev. month" msgid "Jan." -msgstr "" +msgstr "जान." msgctxt "abbrev. month" msgid "Feb." -msgstr "" +msgstr "फेब." msgctxt "abbrev. month" msgid "March" -msgstr "" +msgstr "मार्च" msgctxt "abbrev. month" msgid "April" -msgstr "" +msgstr "एप्रिल" msgctxt "abbrev. month" msgid "May" -msgstr "" +msgstr "मे" msgctxt "abbrev. month" msgid "June" -msgstr "" +msgstr "जून" msgctxt "abbrev. month" msgid "July" -msgstr "" +msgstr "जुलै" msgctxt "abbrev. month" msgid "Aug." -msgstr "" +msgstr "ऑग." msgctxt "abbrev. month" msgid "Sept." -msgstr "" +msgstr "सप्ट." msgctxt "abbrev. month" msgid "Oct." -msgstr "" +msgstr "ऑक्ट." msgctxt "abbrev. month" msgid "Nov." -msgstr "" +msgstr "नोव्ह." msgctxt "abbrev. month" msgid "Dec." -msgstr "" +msgstr "डिस." msgctxt "alt. month" msgid "January" -msgstr "" +msgstr "जानेवारी" msgctxt "alt. month" msgid "February" -msgstr "" +msgstr "फेब्रुवारी" msgctxt "alt. month" msgid "March" -msgstr "" +msgstr "मार्च" msgctxt "alt. month" msgid "April" -msgstr "" +msgstr "एप्रिल" msgctxt "alt. month" msgid "May" -msgstr "" +msgstr "मे" msgctxt "alt. month" msgid "June" -msgstr "" +msgstr "जून" msgctxt "alt. month" msgid "July" -msgstr "" +msgstr "जुलै" msgctxt "alt. month" msgid "August" -msgstr "" +msgstr "ऑगस्ट" msgctxt "alt. month" msgid "September" -msgstr "" +msgstr "सप्टेंबर" msgctxt "alt. month" msgid "October" -msgstr "" +msgstr "ऑक्टोबर" msgctxt "alt. month" msgid "November" -msgstr "" +msgstr "नोव्हेंबर" msgctxt "alt. month" msgid "December" -msgstr "" +msgstr "डिसेंबर" msgid "This is not a valid IPv6 address." -msgstr "" +msgstr "हा योग्य IPv6 पत्ता नाही." #, python-format msgctxt "String to return when truncating text" @@ -1032,110 +1086,121 @@ msgid "%(truncated_text)s…" msgstr "" msgid "or" -msgstr "" +msgstr "किंवा" #. Translators: This string is used as a separator between list elements msgid ", " -msgstr "" +msgstr "," #, python-format -msgid "%d year" -msgid_plural "%d years" +msgid "%(num)d year" +msgid_plural "%(num)d years" msgstr[0] "" msgstr[1] "" #, python-format -msgid "%d month" -msgid_plural "%d months" +msgid "%(num)d month" +msgid_plural "%(num)d months" msgstr[0] "" msgstr[1] "" #, python-format -msgid "%d week" -msgid_plural "%d weeks" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" msgstr[0] "" msgstr[1] "" #, python-format -msgid "%d day" -msgid_plural "%d days" +msgid "%(num)d day" +msgid_plural "%(num)d days" msgstr[0] "" msgstr[1] "" #, python-format -msgid "%d hour" -msgid_plural "%d hours" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" msgstr[0] "" msgstr[1] "" #, python-format -msgid "%d minute" -msgid_plural "%d minutes" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" msgstr[0] "" msgstr[1] "" -msgid "0 minutes" -msgstr "" - msgid "Forbidden" -msgstr "" +msgstr "निषिद्ध" msgid "CSRF verification failed. Request aborted." -msgstr "" +msgstr "CSRF चाचणी अयशस्वी झाली. विनंती रद्द केली." msgid "" "You are seeing this message because this HTTPS site requires a “Referer " -"header” to be sent by your Web browser, but none was sent. This header is " +"header” to be sent by your web browser, but none was sent. This header is " "required for security reasons, to ensure that your browser is not being " "hijacked by third parties." msgstr "" +"तुम्हाला हा सनदेश दिसत आहे कारण या HTTPS संकेतस्थळाला तुमच्या वेब ब्राउझरद्वारे \"रेफरर " +"हेडर\" पाठवण्याची आवश्यकता आहे, परंतु कोणतेही पाठवले नाही. तुमचा ब्राउझर तृतीय पक्षांकडून " +"हायजॅक केला जात नाही याची खात्री करण्यासाठी सुरक्षिततेच्या दृष्टीने हे शीर्षलेख आवश्यक आहे." msgid "" "If you have configured your browser to disable “Referer” headers, please re-" "enable them, at least for this site, or for HTTPS connections, or for “same-" "origin” requests." msgstr "" +"किमान या साइटसाठी किंवा HTTPS कनेक्शनसाठी किंवा “समान-मूळ” विनंत्यांसाठी, तुम्ही तुमचे " +"ब्राउझर “रेफरर” हेडर अक्षम केले असल्यास, कृपया ते पुन्हा-सक्षम करा." msgid "" "If you are using the tag or " "including the “Referrer-Policy: no-referrer” header, please remove them. The " "CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." +"If you’re concerned about privacy, use alternatives like for links to third-party sites." msgstr "" +"तुम्ही जोडणी वापरत असल्यास किंवा \"रेफरर-पॉलिसी: नो-रेफरर\" हेडर समाविष्ट करत " +"असल्यास, कृपया ते काढून टाका. CSRF संरक्षणासाठी \"रेफरर\" हेडर कठोर रेफरर तपासणी करणे " +"आवश्यक आहे. तुम्हाला गोपनीयतेबद्दल काळजी वाटत असल्यास, तृतीय-पक्ष स्थळाच्या दुव्यासाठी सारखे पर्याय वापरा." msgid "" "You are seeing this message because this site requires a CSRF cookie when " "submitting forms. This cookie is required for security reasons, to ensure " "that your browser is not being hijacked by third parties." msgstr "" +"तुम्हाला हा संदेश दिसत आहे कारण अर्ज सुपूर्त करताना या स्थळाला CSRF कुकी आवश्यक आहे. तुमचा " +"ब्राउझर तृतीय पक्षांकडून हायजॅक केला जात नाही याची खात्री करण्यासाठी ही कुकी " +"सुरक्षिततेच्या कारणांसाठी आवश्यक आहे." msgid "" "If you have configured your browser to disable cookies, please re-enable " "them, at least for this site, or for “same-origin” requests." msgstr "" +"किमान या साइटसाठी किंवा \"समान-मूळ\" विनंत्यांसाठी, कृपया अक्षम केलेल्या ब्राउझर कुकीज " +"पुन्हा सक्षम करा." msgid "More information is available with DEBUG=True." -msgstr "" +msgstr "अधिक माहिती DEBUG=True सह उपलब्ध आहे." msgid "No year specified" -msgstr "" +msgstr "कोणतेही वर्ष नमूद केलेले नाही" msgid "Date out of range" -msgstr "" +msgstr "पल्ल्याच्या बाहेरची दिनांक" msgid "No month specified" -msgstr "" +msgstr "कोणताही महिना निर्दिष्ट केलेला नाही" msgid "No day specified" -msgstr "" +msgstr "कोणताही दिवस निर्दिष्ट केलेला नाही" msgid "No week specified" -msgstr "" +msgstr "कोणताही आठवडा निर्दिष्ट केलेला नाही" #, python-format msgid "No %(verbose_name_plural)s available" -msgstr "" +msgstr "कोणतेही %(verbose_name_plural)s उपलब्ध नाहीत" #, python-format msgid "" @@ -1149,64 +1214,67 @@ msgstr "" #, python-format msgid "No %(verbose_name)s found matching the query" -msgstr "" +msgstr "क्वेरीसह जुळणारे कोणतेही %(verbose_name)s सापडले नाही" msgid "Page is not “last”, nor can it be converted to an int." msgstr "" #, python-format msgid "Invalid page (%(page_number)s): %(message)s" -msgstr "" +msgstr "अवैध पान (%(page_number)s): %(message)s" #, python-format msgid "Empty list and “%(class_name)s.allow_empty” is False." msgstr "" msgid "Directory indexes are not allowed here." -msgstr "" +msgstr "डिरेक्टरी निर्देशकांना येथे परवानगी नाही." #, python-format msgid "“%(path)s” does not exist" -msgstr "" +msgstr "“%(path)s” अस्तित्वात नाही" #, python-format msgid "Index of %(directory)s" -msgstr "" +msgstr "%(directory)s चे निर्देशांक" -msgid "Django: the Web framework for perfectionists with deadlines." -msgstr "" +msgid "The install worked successfully! Congratulations!" +msgstr "इंस्टॉलेशनने यशस्वीरित्या कार्य केले! अभिनंदन!" #, python-format msgid "" "View release notes for Django %(version)s" msgstr "" - -msgid "The install worked successfully! Congratulations!" -msgstr "" +"डिजांगो %(version)s साठी प्रदर्शित संदेश पहा" #, python-format msgid "" "You are seeing this page because DEBUG=True is in your settings file and you have not configured any " -"URLs." +"%(version)s/ref/settings/#debug\" target=\"_blank\" " +"rel=\"noopener\">DEBUG=True is in your settings file and you have not " +"configured any URLs." msgstr "" +"तुम्ही हे पान पाहत आहात कारण तुमच्या सेटिंग्ज फाइलमध्ये DEBUG=True आहे आणि तुम्ही कोणतीही URL कॉन्फिगर केलेली नाही." msgid "Django Documentation" -msgstr "" +msgstr "जांगो दस्तऐवजीकरण" msgid "Topics, references, & how-to’s" -msgstr "" +msgstr "विषय, संदर्भ, आणि कसे करावे" msgid "Tutorial: A Polling App" -msgstr "" +msgstr "शिकवणी: मतदान अ‍ॅप" msgid "Get started with Django" -msgstr "" +msgstr "जॅंगो सोबत सुरवात करा" msgid "Django Community" -msgstr "" +msgstr "जॅंगो समुदाय" msgid "Connect, get help, or contribute" -msgstr "" +msgstr "जोडा, मदत मिळवा किंवा हातभार लावा" diff --git a/django/conf/locale/uz/LC_MESSAGES/django.mo b/django/conf/locale/uz/LC_MESSAGES/django.mo index 57f89e8f930..b003df83ef1 100644 Binary files a/django/conf/locale/uz/LC_MESSAGES/django.mo and b/django/conf/locale/uz/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/uz/LC_MESSAGES/django.po b/django/conf/locale/uz/LC_MESSAGES/django.po index 4e9b6cfa775..ad57ba91b7a 100644 --- a/django/conf/locale/uz/LC_MESSAGES/django.po +++ b/django/conf/locale/uz/LC_MESSAGES/django.po @@ -4,15 +4,16 @@ # Abdulaminkhon Khaydarov , 2020 # Bedilbek Khamidov , 2019 # Claude Paroz , 2020 +# Shukrullo Turgunov , 2023 # Sukhrobbek Ismatov , 2019 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-05-19 20:23+0200\n" -"PO-Revision-Date: 2020-07-25 17:08+0000\n" -"Last-Translator: Abdulaminkhon Khaydarov \n" -"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-25 06:49+0000\n" +"Last-Translator: Shukrullo Turgunov , 2023\n" +"Language-Team: Uzbek (http://app.transifex.com/django/django/language/uz/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -52,6 +53,9 @@ msgstr "Bosniya tili" msgid "Catalan" msgstr "Katalon tili" +msgid "Central Kurdish (Sorani)" +msgstr "" + msgid "Czech" msgstr "Chex tili" @@ -208,6 +212,9 @@ msgstr "Mo'g'ul tili" msgid "Marathi" msgstr "Marati tili" +msgid "Malay" +msgstr "" + msgid "Burmese" msgstr "Birma tili" @@ -289,6 +296,9 @@ msgstr "Tatar tili" msgid "Udmurt" msgstr "Udmurt tili" +msgid "Uyghur" +msgstr "" + msgid "Ukrainian" msgstr "Ukrain tili" @@ -319,6 +329,11 @@ msgstr "Statik fayllar" msgid "Syndication" msgstr "Sindikatsiya" +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + msgid "That page number is not an integer" msgstr "Bu sahifa raqami butun son emas" @@ -344,8 +359,8 @@ msgstr "To'g'ri elektron pochta manzilini kiriting." msgid "" "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." msgstr "" -"Harflar, raqamlar, pastki chiziqlar yoki chiziqlardan iborat to'g'ri \"slug" -"\" ni kiriting." +"Harflar, raqamlar, pastki chiziqlar yoki chiziqlardan iborat to'g'ri " +"\"slug\" ni kiriting." msgid "" "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " @@ -382,6 +397,16 @@ msgid "Ensure this value is greater than or equal to %(limit_value)s." msgstr "" "Ushbu qiymat %(limit_value)s dan katta yoki unga teng ekanligini tekshiring." +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " @@ -446,6 +471,10 @@ msgstr "va" msgid "%(model_name)s with this %(field_labels)s already exists." msgstr "%(field_labels)s bilan %(model_name)s allaqachon mavjud." +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + #, python-format msgid "Value %(value)r is not a valid choice." msgstr "%(value)r qiymati to'g'ri tanlov emas." @@ -460,8 +489,8 @@ msgstr "Bu maydon bo‘sh bo‘lishi mumkin emas." msgid "%(model_name)s with this %(field_label)s already exists." msgstr "\"%(field_label)s\" %(model_name)s allaqachon mavjud." -#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. -#. Eg: "Title must be unique for pub_date year" +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" #, python-format msgid "" "%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." @@ -490,6 +519,9 @@ msgstr "Mantiqiy (Rost yoki Yolg'on)" msgid "String (up to %(max_length)s)" msgstr "Birikma uzunligi (%(max_length)s gacha)" +msgid "String (unlimited)" +msgstr "" + msgid "Comma-separated integers" msgstr "Vergul bilan ajratilgan butun sonlar" @@ -572,6 +604,9 @@ msgstr "Butun son" msgid "Big (8 byte) integer" msgstr "Katta (8 bayt) butun son" +msgid "Small integer" +msgstr "Kichik butun son" + msgid "IPv4 address" msgstr "IPv4 manzili" @@ -598,9 +633,6 @@ msgstr "Musbat kichik butun son" msgid "Slug (up to %(max_length)s)" msgstr "Slug uzunligi (%(max_length)s gacha)" -msgid "Small integer" -msgstr "Kichik butun son" - msgid "Text" msgstr "Matn" @@ -749,18 +781,21 @@ msgstr ":" msgid "(Hidden field %(name)s) %(error)s" msgstr "(Yashirilgan maydon %(name)s) %(error)s" -msgid "ManagementForm data is missing or has been tampered with" -msgstr "ManagementForm ma'lumotlari yo'q yoki o'zgartirilgan" +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" #, python-format -msgid "Please submit %d or fewer forms." -msgid_plural "Please submit %d or fewer forms." -msgstr[0] "Iltimos, %d ta yoki kamroq forma topshiring." +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" #, python-format -msgid "Please submit %d or more forms." -msgid_plural "Please submit %d or more forms." -msgstr[0] "Iltimos, %d ta yoki ko'proq forma topshiring." +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" msgid "Order" msgstr "Buyurtma" @@ -1098,34 +1133,34 @@ msgid ", " msgstr "," #, python-format -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "%dyil" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d yil" #, python-format -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "%doy" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)doy" #, python-format -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "%dhafta" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hafta" #, python-format -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "%dkun" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d kun" #, python-format -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "%dsoat" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d soat" #, python-format -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "%dminut" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d daqiqa" msgid "Forbidden" msgstr "Taqiqlangan" @@ -1135,15 +1170,10 @@ msgstr "CSRF tekshiruvi amalga oshmadi. So‘rov bekor qilindi." msgid "" "You are seeing this message because this HTTPS site requires a “Referer " -"header” to be sent by your Web browser, but none was sent. This header is " +"header” to be sent by your web browser, but none was sent. This header is " "required for security reasons, to ensure that your browser is not being " "hijacked by third parties." msgstr "" -"Siz ushbu xabarni ko'rmoqdasiz, chunki bu HTTPS saytida veb-brauzeringiz " -"tomonidan \"Referer header\" yuborilishi talab qilinadi, ammo hech biri " -"yuborilmadi. Ushbu sarlavha xavfsizlik nuqtai nazaridan, brauzeringizni " -"uchinchi shaxslar tomonidan o'g'irlanmasligini ta'minlash uchun talab " -"qilinadi." msgid "" "If you have configured your browser to disable “Referer” headers, please re-" @@ -1159,8 +1189,8 @@ msgid "" "If you are using the tag or " "including the “Referrer-Policy: no-referrer” header, please remove them. The " "CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." +"If you’re concerned about privacy, use alternatives like for links to third-party sites." msgstr "" "Agar siz yorlig'idan yoki " "\"Referrer-Policy: no-referer\" sarlavhasidan foydalanayotgan bo'lsangiz, " @@ -1249,8 +1279,8 @@ msgstr "\"%(path)s\" mavjud emas" msgid "Index of %(directory)s" msgstr "%(directory)s indeksi" -msgid "Django: the Web framework for perfectionists with deadlines." -msgstr "Django: muddati chegaralangan perfektsionistlar uchun veb freymvork." +msgid "The install worked successfully! Congratulations!" +msgstr "O'rnatish muvaffaqiyatli amalga oshdi! Tabriklaymiz!" #, python-format msgid "" @@ -1261,20 +1291,17 @@ msgstr "" "com/en/%(version)s/releases/\" target=\"_blank\" rel=\"noopener\"> " "nashrlarni ko'rish" -msgid "The install worked successfully! Congratulations!" -msgstr "O'rnatish muvaffaqiyatli amalga oshdi! Tabriklaymiz!" - #, python-format msgid "" "You are seeing this page because DEBUG=True is in your settings file and you have not configured any " -"URLs." +"%(version)s/ref/settings/#debug\" target=\"_blank\" " +"rel=\"noopener\">DEBUG=True is in your settings file and you have not " +"configured any URLs." msgstr "" "Siz ushbu sahifani ko'rmoqdasiz, chunki DEBUG = True ifodasi sizning sozlamalar faylingizda ko'rsatilgan va " -"siz biron bir URL manzilini to'gri sozlamagansiz." +"com/en/%(version)s/ref/settings/#debug\" target=\"_blank\" " +"rel=\"noopener\">DEBUG = True ifodasi sizning sozlamalar faylingizda " +"ko'rsatilgan va siz biron bir URL manzilini to'gri sozlamagansiz." msgid "Django Documentation" msgstr "Django Hujjatlari" diff --git a/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo b/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo index 39927e8d8fe..55517ea7b6e 100644 Binary files a/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo and b/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/zh_Hans/LC_MESSAGES/django.po b/django/conf/locale/zh_Hans/LC_MESSAGES/django.po index c0c6d6065fd..097e77d4b4f 100644 --- a/django/conf/locale/zh_Hans/LC_MESSAGES/django.po +++ b/django/conf/locale/zh_Hans/LC_MESSAGES/django.po @@ -7,6 +7,7 @@ # Fan Xu , 2022 # Ford Guo , 2022 # Huanqun Yang, 2022 +# jack yang, 2023 # jamin M , 2019 # Jannis Leidel , 2011 # Kevin Sze , 2012 @@ -32,17 +33,17 @@ # ced773123cfad7b4e8b79ca80f736af9, 2011-2012 # Ziya Tang , 2018 # 付峥 , 2018 -# Fangjiaqi77 <370358679@qq.com>, 2020 +# LatteFang <370358679@qq.com>, 2020 # Kevin Sze , 2012 # 高乐喆 , 2023 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-17 02:13-0600\n" -"PO-Revision-Date: 2023-04-25 06:49+0000\n" -"Last-Translator: 高乐喆 , 2023\n" -"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-25 06:49+0000\n" +"Last-Translator: jack yang, 2023\n" +"Language-Team: Chinese (China) (http://app.transifex.com/django/django/" "language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -326,6 +327,9 @@ msgstr "鞑靼语" msgid "Udmurt" msgstr "乌德穆尔特语" +msgid "Uyghur" +msgstr "维吾尔语" + msgid "Ukrainian" msgstr "乌克兰语" @@ -420,6 +424,14 @@ msgstr "确保该值大于或等于%(limit_value)s。" msgid "Ensure this value is a multiple of step size %(limit_value)s." msgstr "确保该值是步长的倍数%(limit_value)s" +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"确保此值是步长 %(limit_value)s 的倍数,从 %(offset)s 开始,例如 " +"%(offset)s、%(valid_value1)s、%(valid_value2)s 等等。" + #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py index 16650234347..aa43718cd68 100644 --- a/django/contrib/admin/checks.py +++ b/django/contrib/admin/checks.py @@ -532,7 +532,7 @@ def _check_filter_item(self, obj, field_name, label): field=field_name, option=label, obj=obj, id="admin.E019" ) else: - if not field.many_to_many: + if not field.many_to_many or isinstance(field, models.ManyToManyRel): return must_be( "a many-to-many field", option=label, obj=obj, id="admin.E020" ) diff --git a/django/contrib/admin/filters.py b/django/contrib/admin/filters.py index 06dedf87279..675c4a5d499 100644 --- a/django/contrib/admin/filters.py +++ b/django/contrib/admin/filters.py @@ -5,6 +5,7 @@ Each filter subclass knows how to display a filter for a field that passes a certain test -- e.g. being a DateField or ForeignKey. """ + import datetime from django.contrib.admin.exceptions import NotRegistered diff --git a/django/contrib/admin/locale/af/LC_MESSAGES/django.mo b/django/contrib/admin/locale/af/LC_MESSAGES/django.mo index 5d9adc95c2c..bb91c2e475f 100644 Binary files a/django/contrib/admin/locale/af/LC_MESSAGES/django.mo and b/django/contrib/admin/locale/af/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admin/locale/af/LC_MESSAGES/django.po b/django/contrib/admin/locale/af/LC_MESSAGES/django.po index 65ab02dd6a2..ff97eaecd24 100644 --- a/django/contrib/admin/locale/af/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/af/LC_MESSAGES/django.po @@ -416,7 +416,7 @@ msgid "Show counts" msgstr "Wys tellings" msgid "Clear all filters" -msgstr "Verwyder filters" +msgstr "Verwyder alle filters" msgid "Remove from sorting" msgstr "Verwyder uit sortering" @@ -642,6 +642,7 @@ msgstr "Wys gekose %(model)s" msgid "Thanks for spending some quality time with the web site today." msgstr "" +"Dankie vir die kwaliteittyd wat u met die webwerf deurgebring het vandag." msgid "Log in again" msgstr "Meld weer aan" diff --git a/django/contrib/admin/locale/ckb/LC_MESSAGES/django.mo b/django/contrib/admin/locale/ckb/LC_MESSAGES/django.mo index 8f4d8319e32..e4625809b24 100644 Binary files a/django/contrib/admin/locale/ckb/LC_MESSAGES/django.mo and b/django/contrib/admin/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admin/locale/ckb/LC_MESSAGES/django.po b/django/contrib/admin/locale/ckb/LC_MESSAGES/django.po index 83eba5831af..f6b80d6d806 100644 --- a/django/contrib/admin/locale/ckb/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/ckb/LC_MESSAGES/django.po @@ -6,14 +6,14 @@ # Bakhtawar Barzan, 2021 # kosar tofiq , 2020 # pejar hewrami , 2020 -# Swara , 2022 +# Swara , 2022,2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Abdulla Dlshad, 2023\n" +"PO-Revision-Date: 2013-04-25 07:05+0000\n" +"Last-Translator: Swara , 2022,2024\n" "Language-Team: Central Kurdish (http://app.transifex.com/django/django/" "language/ckb/)\n" "MIME-Version: 1.0\n" @@ -184,7 +184,7 @@ msgstr "" "دانەیەک زیاتر." msgid "Select this object for an action - {}" -msgstr "" +msgstr "ئەم تەنە هەڵبژێرە بۆ کردارێک - {}" #, python-brace-format msgid "The {name} “{obj}” was added successfully." @@ -351,7 +351,7 @@ msgid "Clear selection" msgstr "پاککردنەوەی هەڵبژاردن" msgid "Breadcrumbs" -msgstr "" +msgstr "وردەنان" #, python-format msgid "Models in the %(name)s application" @@ -389,7 +389,7 @@ msgid "Enter a new password for the user %(username)s." msgstr "تێپەڕەوشەی نوێ بۆ بەکارهێنەری %(username)s بنوسە" msgid "Skip to main content" -msgstr "" +msgstr "تێیپەڕێنە بۆ ناوەڕۆکی سەرەکی" msgid "Welcome," msgstr "بەخێربێیت،" @@ -417,10 +417,10 @@ msgid "Filter" msgstr "پاڵاوتن" msgid "Hide counts" -msgstr "" +msgstr "ژماردن بشارەوە" msgid "Show counts" -msgstr "" +msgstr "ژماردن پیشانبدە" msgid "Clear all filters" msgstr "پاکردنەوەی هەموو پاڵاوتنەکان" @@ -436,13 +436,13 @@ msgid "Toggle sorting" msgstr "ڕیزکردنی پێچەوانە" msgid "Toggle theme (current theme: auto)" -msgstr "" +msgstr "گۆڕینی ڕووکار (ڕووکاری ئێستا: خۆکار)" msgid "Toggle theme (current theme: light)" -msgstr "" +msgstr "گۆڕینی ڕووکار (ڕووکاری ئێستا: ڕووناک)" msgid "Toggle theme (current theme: dark)" -msgstr "" +msgstr "گۆڕینی ڕووکار (ڕووکاری ئێستا: تاریک)" msgid "Delete" msgstr "سڕینەوە" @@ -531,13 +531,13 @@ msgid "None available" msgstr "هیچ شتيک بەردەست نییە" msgid "Added:" -msgstr "" +msgstr "زیادکرا:" msgid "Changed:" -msgstr "" +msgstr "گۆڕدرا:" msgid "Deleted:" -msgstr "" +msgstr "سڕایەوە:" msgid "Unknown content" msgstr "ناوەڕۆکی نەزانراو" @@ -566,7 +566,7 @@ msgid "Toggle navigation" msgstr "کردنەوەو داخستنی ڕێنیشاندەر" msgid "Sidebar" -msgstr "" +msgstr "شریتی لاتەنیشت" msgid "Start typing to filter…" msgstr "دەست بکە بە نوسین بۆ پاڵاوتن..." @@ -585,8 +585,8 @@ msgstr "کردار" msgid "entry" msgid_plural "entries" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "تۆمار" +msgstr[1] "تۆمارەکان" msgid "" "This object doesn’t have a change history. It probably wasn’t added via this " @@ -749,7 +749,7 @@ msgid "Reset my password" msgstr "دانانەوەی تێپەڕەوشەکەم" msgid "Select all objects on this page for an action" -msgstr "" +msgstr "هەموو تەنەکان لەم لاپەڕەیە بۆ کردارێک هەڵبژێرە" msgid "All dates" msgstr "هەموو بەروارەکان" diff --git a/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.mo b/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.mo index f7415be678d..95cbda79074 100644 Binary files a/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.mo and b/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.mo differ diff --git a/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.po b/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.po index 69f7a731ddf..23b1fd0f87a 100644 --- a/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.po +++ b/django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.po @@ -4,14 +4,14 @@ # Bakhtawar Barzan, 2021 # Bakhtawar Barzan, 2021 # Mariusz Felisiak , 2023 -# Swara , 2022-2023 +# Swara , 2022-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-04-25 07:59+0000\n" -"Last-Translator: Mariusz Felisiak , 2023\n" +"POT-Creation-Date: 2023-09-18 15:04-0300\n" +"PO-Revision-Date: 2024-01-20 07:59+0000\n" +"Last-Translator: Swara , 2022-2024\n" "Language-Team: Central Kurdish (http://app.transifex.com/django/django/" "language/ckb/)\n" "MIME-Version: 1.0\n" @@ -68,7 +68,7 @@ msgstr "" #, javascript-format msgid "Type into this box to filter down the list of selected %s." -msgstr "" +msgstr "لەم بوخچەدا بنووسە بۆ ئەوەی لیستی هەڵبژێردراوەکان بپاڵێویت %s." msgid "Remove all" msgstr "لابردنی هەمووی" @@ -80,8 +80,8 @@ msgstr "کرتە بکە بۆ لابردنی هەموو ئەوانەی هەڵبژ #, javascript-format msgid "%s selected option not visible" msgid_plural "%s selected options not visible" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%sبژاردەی هەڵبژێردراو نابینرێت" +msgstr[1] "%s هەڵبژاردە هەڵبژێردراوەکان نابینرێن" msgid "%(sel)s of %(cnt)s selected" msgid_plural "%(sel)s of %(cnt)s selected" @@ -245,6 +245,55 @@ msgctxt "abbrev. month December" msgid "Dec" msgstr "‎بەفرانبار" +msgid "Sunday" +msgstr "یەکشەممە" + +msgid "Monday" +msgstr "دووشەممە" + +msgid "Tuesday" +msgstr "سێشەممە" + +msgid "Wednesday" +msgstr "چوارشەممە" + +msgid "Thursday" +msgstr "پێنجشەممە" + +msgid "Friday" +msgstr "هەینی" + +msgid "Saturday" +msgstr "شەممە" + +msgctxt "abbrev. day Sunday" +msgid "Sun" +msgstr "یەک" + +msgctxt "abbrev. day Monday" +msgid "Mon" +msgstr "دوو" + +msgctxt "abbrev. day Tuesday" +msgid "Tue" +msgstr "سێ" + +msgctxt "abbrev. day Wednesday" +msgid "Wed" +msgstr "چوار" + +msgctxt "abbrev. day Thursday" +msgid "Thur" +msgstr "پێنج" + +msgctxt "abbrev. day Friday" +msgid "Fri" +msgstr "هەینی" + +msgctxt "abbrev. day Saturday" +msgid "Sat" +msgstr "شەم" + msgctxt "one letter Sunday" msgid "S" msgstr "ی" diff --git a/django/contrib/admin/locale/mn/LC_MESSAGES/django.mo b/django/contrib/admin/locale/mn/LC_MESSAGES/django.mo index 82cb0bbb8e2..cf857e049ec 100644 Binary files a/django/contrib/admin/locale/mn/LC_MESSAGES/django.mo and b/django/contrib/admin/locale/mn/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admin/locale/mn/LC_MESSAGES/django.po b/django/contrib/admin/locale/mn/LC_MESSAGES/django.po index 48c2e133dc4..c5d0cb44870 100644 --- a/django/contrib/admin/locale/mn/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/mn/LC_MESSAGES/django.po @@ -4,17 +4,18 @@ # Ankhbayar , 2013 # Jannis Leidel , 2011 # jargalan , 2011 +# Turmunkh Batkhuyag, 2023 # Zorig, 2016 -# Анхбаяр Анхаа , 2013-2016,2018-2019,2021 +# Анхбаяр Анхаа , 2013-2016,2018-2019,2021,2023 # Баясгалан Цэвлээ , 2011,2017 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-09-21 10:22+0200\n" -"PO-Revision-Date: 2021-11-16 17:18+0000\n" -"Last-Translator: Анхбаяр Анхаа \n" -"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-25 07:05+0000\n" +"Last-Translator: Turmunkh Batkhuyag, 2023\n" +"Language-Team: Mongolian (http://app.transifex.com/django/django/language/" "mn/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -24,7 +25,7 @@ msgstr "" #, python-format msgid "Delete selected %(verbose_name_plural)s" -msgstr "Сонгосон %(verbose_name_plural)s-ийг устга" +msgstr "Сонгосон %(verbose_name_plural)s-ийг устгах" #, python-format msgid "Successfully deleted %(count)d %(items)s." @@ -74,10 +75,10 @@ msgid "Has date" msgstr "Огноотой" msgid "Empty" -msgstr "" +msgstr "Хоосон" msgid "Not empty" -msgstr "" +msgstr "Хоосон биш" #, python-format msgid "" @@ -152,7 +153,7 @@ msgstr "Лог бүртгэлийн обект" #, python-brace-format msgid "Added {name} “{object}”." -msgstr "" +msgstr "Нэмсэн {name} “{object}”." msgid "Added." msgstr "Нэмэгдсэн." @@ -162,7 +163,7 @@ msgstr "ба" #, python-brace-format msgid "Changed {fields} for {name} “{object}”." -msgstr "" +msgstr "Changed {fields} for {name} “{object}”." #, python-brace-format msgid "Changed {fields}." @@ -170,7 +171,7 @@ msgstr "Өөрчлөгдсөн {fields}." #, python-brace-format msgid "Deleted {name} “{object}”." -msgstr "" +msgstr "Устгасан {name} “{object}”." msgid "No fields changed." msgstr "Өөрчилсөн талбар алга байна." @@ -180,10 +181,15 @@ msgstr "Хоосон" msgid "Hold down “Control”, or “Command” on a Mac, to select more than one." msgstr "" +"Нэгээс олныг сонгохын тулд \"Control\" эсвэл Mac компьютер дээр \"Command\" " +"товчоо дарна уу." + +msgid "Select this object for an action - {}" +msgstr "Сонголтоо хийхийн тулд энэ объектыг сонгоно уу - {}" #, python-brace-format msgid "The {name} “{obj}” was added successfully." -msgstr "" +msgstr "{name} “{obj}” амжилттай нэмэгдлээ." msgid "You may edit it again below." msgstr "Та дараахийг дахин засах боломжтой" @@ -192,25 +198,30 @@ msgstr "Та дараахийг дахин засах боломжтой" msgid "" "The {name} “{obj}” was added successfully. You may add another {name} below." msgstr "" +"{name} “{obj}” амжилттай нэмэгдлээ. Та доорх {name}-ийг нэмэх боломжтой." #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may edit it again below." msgstr "" +"{name} \"{obj}\" амжилттай өөрчлөгдлөө. Та доорх талбаруудыг дахин засварлах " +"боломжтой." #, python-brace-format msgid "The {name} “{obj}” was added successfully. You may edit it again below." msgstr "" +" {name} \"{obj}\" амжилттай нэмэгдлээ. Та доор дахин шинэчлэх боломжтой." #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may add another {name} " "below." msgstr "" +"\"{name}\" \"{obj}\" амжилттай өөрчлөгдлөө. Доорх {name}-г нэмж оруулна уу." #, python-brace-format msgid "The {name} “{obj}” was changed successfully." -msgstr "" +msgstr "{name} \" {obj} \" амжилттай өөрчлөгдлөө." msgid "" "Items must be selected in order to perform actions on them. No items have " @@ -223,11 +234,11 @@ msgstr "Үйлдэл сонгоогүй." #, python-format msgid "The %(name)s “%(obj)s” was deleted successfully." -msgstr "" +msgstr "%(name)s “%(obj)s” амжилттай устгагдлаа." #, python-format msgid "%(name)s with ID “%(key)s” doesn’t exist. Perhaps it was deleted?" -msgstr "" +msgstr "“%(key)s” ID-тай %(name)sбайхгүй байна. Магадгүй устсан уу?" #, python-format msgid "Add %s" @@ -264,8 +275,9 @@ msgstr "%(cnt)s оос 0 сонгосон" msgid "Change history: %s" msgstr "Өөрчлөлтийн түүх: %s" -#. Translators: Model verbose name and instance representation, -#. suitable to be an item in a list. +#. Translators: Model verbose name and instance +#. representation, suitable to be an item in a +#. list. #, python-format msgid "%(class_name)s %(instance)s" msgstr "%(instance)s %(class_name)s" @@ -298,7 +310,7 @@ msgid "Page not found" msgstr "Хуудас олдсонгүй." msgid "We’re sorry, but the requested page could not be found." -msgstr "" +msgstr "Уучлаарай, хүссэн хуудас олдсонгүй." msgid "Home" msgstr "Нүүр" @@ -316,6 +328,8 @@ msgid "" "There’s been an error. It’s been reported to the site administrators via " "email and should be fixed shortly. Thanks for your patience." msgstr "" +"Алдаа гарсан байна. И-мэйлээр админуудад мэдэгдэгдсэн бөгөөд тун удахгүй " +"засах болно. Хамтран ажилласанд баярлалаа." msgid "Run the selected action" msgstr "Сонгосон үйлдэлийг ажилуулах" @@ -333,6 +347,9 @@ msgstr "Бүгдийг сонгох %(total_count)s %(module_name)s" msgid "Clear selection" msgstr "Сонгосонг цэвэрлэх" +msgid "Breadcrumbs" +msgstr "Талхны үүрмэг" + #, python-format msgid "Models in the %(name)s application" msgstr "%(name)s хэрэглүүр дэх моделууд." @@ -344,12 +361,14 @@ msgid "View" msgstr "Харах" msgid "You don’t have permission to view or edit anything." -msgstr "" +msgstr "Та ямар ч харах эсвэл засах эрхгүй байна." msgid "" "First, enter a username and password. Then, you’ll be able to edit more user " "options." msgstr "" +"Эхлээд, хэрэглэгчийн нэр болон нууц үгээ оруулна уу. Дараа нь, та бусад " +"хэрэглэгчийн сонголтуудыг засварлах боломжтой болно." msgid "Enter a username and password." msgstr "Хэрэглэгчийн нэр ба нууц үгээ оруулна." @@ -358,15 +377,17 @@ msgid "Change password" msgstr "Нууц үг өөрчлөх" msgid "Please correct the error below." -msgstr "Доорх алдааг засна уу" - -msgid "Please correct the errors below." -msgstr "Доор гарсан алдаануудыг засна уу." +msgid_plural "Please correct the errors below." +msgstr[0] "Та доорх алдаануудыг засна уу." +msgstr[1] "Та доорх алдаануудыг засна уу." #, python-format msgid "Enter a new password for the user %(username)s." msgstr "%(username)s.хэрэглэгчид шинэ нууц үг оруулна уу." +msgid "Skip to main content" +msgstr "Үндсэн агуулга руу шилжих" + msgid "Welcome," msgstr "Тавтай морилно уу" @@ -392,8 +413,14 @@ msgstr "Сайтаас харах" msgid "Filter" msgstr "Шүүлтүүр" +msgid "Hide counts" +msgstr "Тооцоог нуух" + +msgid "Show counts" +msgstr "Тооцоог харуулах" + msgid "Clear all filters" -msgstr "" +msgstr "Бүх шүүлтүүрийг арилгах" msgid "Remove from sorting" msgstr "Эрэмблэлтээс хасах" @@ -405,6 +432,15 @@ msgstr "Эрэмблэх урьтамж: %(priority_number)s" msgid "Toggle sorting" msgstr "Эрэмбэлэлтийг харуул" +msgid "Toggle theme (current theme: auto)" +msgstr "Загварыг сэлгэх (одоогийн загвар: авто)" + +msgid "Toggle theme (current theme: light)" +msgstr "Загварыг сэлгэх (одоогийн загвар: өдрийн)" + +msgid "Toggle theme (current theme: dark)" +msgstr "Загварыг сэлгэх (одоогийн горим: шөнийн)" + msgid "Delete" msgstr "Устгах" @@ -437,7 +473,7 @@ msgid "Objects" msgstr "Бичлэгүүд" msgid "Yes, I’m sure" -msgstr "" +msgstr "Тийм, би итгэлтэй." msgid "No, take me back" msgstr "Үгүй, намайг буцаа" @@ -478,7 +514,7 @@ msgid " By %(filter_title)s " msgstr " %(filter_title)s -ээр" msgid "Summary" -msgstr "Нийт" +msgstr "Хураангуй" msgid "Recent actions" msgstr "Сүүлд хийсэн үйлдлүүд" @@ -489,6 +525,15 @@ msgstr "Миний үйлдлүүд" msgid "None available" msgstr "Үйлдэл алга" +msgid "Added:" +msgstr "Нэмсэн:" + +msgid "Changed:" +msgstr "Өөрчилсөн:" + +msgid "Deleted:" +msgstr "Устгасан:" + msgid "Unknown content" msgstr "Тодорхойгүй агуулга" @@ -497,6 +542,9 @@ msgid "" "database tables have been created, and make sure the database is readable by " "the appropriate user." msgstr "" +"Таны өгөгдлийн санг суулгахад ямар нэг алдаа гарлаа байна. Өгөгдлийн сангийн " +"тохирох хүснэгтүүдийг үүсгэсэн эсэхийг шалгаад, өгөгдлийн санг тохирох " +"хэрэглэгч унших боломжтой эсэхийг шалгаарай." #, python-format msgid "" @@ -510,13 +558,16 @@ msgid "Forgotten your password or username?" msgstr "Таны мартсан нууц үг эсвэл нэрвтэр нэр?" msgid "Toggle navigation" -msgstr "" +msgstr "Жолоодлого солбих" + +msgid "Sidebar" +msgstr "Хажуугийн самбар" msgid "Start typing to filter…" -msgstr "" +msgstr "Шүүхийн тулд бичиж эхлэх..." msgid "Filter navigation items" -msgstr "" +msgstr "Жолоодлогын зүйлсийг шүүх" msgid "Date/time" msgstr "Огноо/цаг" @@ -527,10 +578,17 @@ msgstr "Хэрэглэгч" msgid "Action" msgstr "Үйлдэл" +msgid "entry" +msgid_plural "entries" +msgstr[0] "оролт" +msgstr[1] "оролт" + msgid "" "This object doesn’t have a change history. It probably wasn’t added via this " "admin site." msgstr "" +"Энэ объектод өөрчлөлтийн түүх байхгүй байна. Админ сайтаар нэмээгүй байх " +"магадлалтай." msgid "Show all" msgstr "Бүгдийг харуулах" @@ -581,8 +639,12 @@ msgstr "Өөр %(model)s нэмэх" msgid "Delete selected %(model)s" msgstr "Сонгосон %(model)s устгах" +#, python-format +msgid "View selected %(model)s" +msgstr "View selected %(model)s" + msgid "Thanks for spending some quality time with the web site today." -msgstr "" +msgstr "Өнөөдөр вэб сайтад цаг заваа зарцуулсанд баярлалаа." msgid "Log in again" msgstr "Ахин нэвтрэх " @@ -597,6 +659,8 @@ msgid "" "Please enter your old password, for security’s sake, and then enter your new " "password twice so we can verify you typed it in correctly." msgstr "" +"Та аюулгүй байдлын үүднээс хуучин нууц үгээ оруулна уу, тэгээд шинэ нууц " +"үгээ хоёр удаа оруулнаар бид бичсэн эсэхийг баталгаажуулах боломжтой." msgid "Change my password" msgstr "Нууц үгээ солих" @@ -634,11 +698,15 @@ msgid "" "We’ve emailed you instructions for setting your password, if an account " "exists with the email you entered. You should receive them shortly." msgstr "" +"Бид таны нууц үг тохируулах зааварчилгааг и-мэйлээр илгээлээ. Хэрэв таны " +"оруулсан и-мэйл дээр акаунт байвал хурдан авах ёстой." msgid "" "If you don’t receive an email, please make sure you’ve entered the address " "you registered with, and check your spam folder." msgstr "" +"Хэрэв та имэйл аваагүй бол та бүртгэлтэй хаяг оруулсан эсэхийг шалгана уу, " +"мөн спам хавтасыг шалгана уу." #, python-format msgid "" @@ -652,7 +720,7 @@ msgid "Please go to the following page and choose a new password:" msgstr "Дараах хуудас руу орон шинэ нууц үг сонгоно уу:" msgid "Your username, in case you’ve forgotten:" -msgstr "" +msgstr "Та хэрэглэгчийн нэрээ мартсан бол:" msgid "Thanks for using our site!" msgstr "Манай сайтыг хэрэглэсэнд баярлалаа!" @@ -665,6 +733,8 @@ msgid "" "Forgotten your password? Enter your email address below, and we’ll email " "instructions for setting a new one." msgstr "" +"Нууц үгээ мартсан уу? Доор имэйл хаягаа оруулна уу, бид шинэ нууц үг " +"тохируулах зааврыг имэйлээр илгээнэ." msgid "Email address:" msgstr "Имэйл хаяг:" @@ -672,6 +742,9 @@ msgstr "Имэйл хаяг:" msgid "Reset my password" msgstr "Нууц үгээ шинэчлэх" +msgid "Select all objects on this page for an action" +msgstr "Энэ хуудас дээрх бүх объектуудыг үйлдэл хийхийн тулд сонгоно уу" + msgid "All dates" msgstr "Бүх огноо" diff --git a/django/contrib/admin/locale/mr/LC_MESSAGES/django.mo b/django/contrib/admin/locale/mr/LC_MESSAGES/django.mo index d847b48ad67..51f8c63d965 100644 Binary files a/django/contrib/admin/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/admin/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admin/locale/mr/LC_MESSAGES/django.po b/django/contrib/admin/locale/mr/LC_MESSAGES/django.po index c02c72b1e8e..c7775621942 100644 --- a/django/contrib/admin/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2015-01-18 08:31+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-01-25 07:05+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,108 +18,142 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format -msgid "Successfully deleted %(count)d %(items)s." +msgid "Delete selected %(verbose_name_plural)s" msgstr "" +#, python-format +msgid "Successfully deleted %(count)d %(items)s." +msgstr "यशस्वीरीत्या %(count)d %(items)s घालवले गेले आहेत." + #, python-format msgid "Cannot delete %(name)s" -msgstr "" +msgstr "%(name)s घालवू शकत नाही" msgid "Are you sure?" -msgstr "" - -#, python-format -msgid "Delete selected %(verbose_name_plural)s" -msgstr "" +msgstr "तुम्हाला खात्री आहे का?" msgid "Administration" -msgstr "" +msgstr "प्रशासन" msgid "All" -msgstr "" +msgstr "सर्व" msgid "Yes" -msgstr "" +msgstr "होय" msgid "No" -msgstr "" +msgstr "नाही" msgid "Unknown" -msgstr "" +msgstr "अज्ञात" msgid "Any date" -msgstr "" +msgstr "कोणतीही दिनांक" msgid "Today" -msgstr "" +msgstr "आज" msgid "Past 7 days" -msgstr "" +msgstr "मागील 7 दिवस" msgid "This month" -msgstr "" +msgstr "या महिन्यात" msgid "This year" -msgstr "" +msgstr "यावर्षी" + +msgid "No date" +msgstr "दिनांक नाही" + +msgid "Has date" +msgstr "दिनांक आहे" + +msgid "Empty" +msgstr "रिकामी" + +msgid "Not empty" +msgstr "रिकामी नाही" #, python-format msgid "" "Please enter the correct %(username)s and password for a staff account. Note " "that both fields may be case-sensitive." msgstr "" +"कृपया करून %(username)s आणि कर्मचारी खात्यासाठी अचूक गुप्तशब्द नमूद करा. लक्षात घ्या की " +"दोन्ही राखणे संवेदनशील असू शकतात." msgid "Action:" -msgstr "" +msgstr "क्रिया:" + +#, python-format +msgid "Add another %(verbose_name)s" +msgstr "अजून एक %(verbose_name)s जोडा" + +msgid "Remove" +msgstr "काढा" + +msgid "Addition" +msgstr "वाढ" + +msgid "Change" +msgstr "बदला" + +msgid "Deletion" +msgstr "वगळा" msgid "action time" -msgstr "" +msgstr "क्रियाकाळ" + +msgid "user" +msgstr "वापरकर्ता" + +msgid "content type" +msgstr "सामुग्री प्रकार" msgid "object id" msgstr "" +#. Translators: 'repr' means representation +#. (https://docs.python.org/library/functions.html#repr) msgid "object repr" msgstr "" msgid "action flag" -msgstr "" +msgstr "क्रिया झेंडा" msgid "change message" -msgstr "" +msgstr "लिखित बदला" msgid "log entry" -msgstr "" +msgstr "घटक नोंद" msgid "log entries" -msgstr "" +msgstr "घटक नोंदी" #, python-format -msgid "Added \"%(object)s\"." -msgstr "" +msgid "Added “%(object)s”." +msgstr "“%(object)s” जोडले" #, python-format -msgid "Changed \"%(object)s\" - %(changes)s" -msgstr "" +msgid "Changed “%(object)s” — %(changes)s" +msgstr "“%(object)s” — %(changes)s बदलले" #, python-format -msgid "Deleted \"%(object)s.\"" -msgstr "" +msgid "Deleted “%(object)s.”" +msgstr "\"%(object)s\" घालविले" msgid "LogEntry Object" msgstr "" -msgid "None" +#, python-brace-format +msgid "Added {name} “{object}”." msgstr "" -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "" - -#, python-format -msgid "Changed %s." -msgstr "" +msgid "Added." +msgstr "जोडले." msgid "and" -msgstr "" +msgstr "आणि" #, python-format msgid "Added %(name)s \"%(object)s\"." @@ -133,24 +168,21 @@ msgid "Deleted %(name)s \"%(object)s\"." msgstr "" msgid "No fields changed." -msgstr "" +msgstr "कोणतेही रखाणे बदलले नाहीत." -#, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgid "None" msgstr "" -#, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may add another " -"%(name)s below." -msgstr "" +msgid "Hold down “Control”, or “Command” on a Mac, to select more than one." +msgstr "एकापेक्षा जास्त निवडण्यासाठी \"कंट्रोल\" किंवा मॅक वर \"कमांड\" खटका दाबा" -#, python-format -msgid "The %(name)s \"%(obj)s\" was added successfully." +msgid "Select this object for an action - {}" msgstr "" -#, python-format +msgid "You may edit it again below." +msgstr "तुम्ही ते खाली पुन्हा संपादित करू शकता." + +#, python-brace-format msgid "" "The %(name)s \"%(obj)s\" was changed successfully. You may edit it again " "below." @@ -162,36 +194,52 @@ msgid "" "%(name)s below." msgstr "" -#, python-format -msgid "The %(name)s \"%(obj)s\" was changed successfully." -msgstr "" +#, python-brace-format +msgid "The {name} “{obj}” was added successfully. You may edit it again below." +msgstr "{name} \"{obj}\" यशस्वीरीत्या जोडले गेले आहे. तुम्ही त्याचे पुन्हा संपादन करू शकता." + +#, python-brace-format +msgid "" +"The {name} “{obj}” was changed successfully. You may add another {name} " +"below." +msgstr "{name} \"{obj}\" यशस्वीरीत्या जोडले गेले आहे. तुम्ही त्याचे पुन्हा संपादन करू शकता." + +#, python-brace-format +msgid "The {name} “{obj}” was changed successfully." +msgstr "{name} \"{obj}\" यशस्वीरीत्या बदलले गेले आहे." msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." msgstr "" +"गोष्टींवर क्रिया करण्यासाठी त्या निवडले जाणे आवश्यक आहे. कोणत्याही गोष्टी बदलल्या गेल्या " +"नाहीत." msgid "No action selected." -msgstr "" +msgstr "कोणतीही क्रिया निवडली नाही." #, python-format -msgid "The %(name)s \"%(obj)s\" was deleted successfully." -msgstr "" +msgid "The %(name)s “%(obj)s” was deleted successfully." +msgstr "%(name)s “%(obj)s” यशस्वीरीत्या हटवले गेले आहे." #, python-format -msgid "%(name)s object with primary key %(key)r does not exist." -msgstr "" +msgid "%(name)s with ID “%(key)s” doesn’t exist. Perhaps it was deleted?" +msgstr "%(name)s “%(key)s” ओळखीसह अस्तित्वात नाही. कदाचित ते घालवले असेल ?" #, python-format msgid "Add %s" -msgstr "" +msgstr "जोडा %s" #, python-format msgid "Change %s" -msgstr "" +msgstr "बदला %s" + +#, python-format +msgid "View %s" +msgstr "पहा %s" msgid "Database error" -msgstr "" +msgstr "डेटाबेस त्रुटी" #, python-format msgid "%(count)s %(name)s was changed successfully." @@ -213,8 +261,9 @@ msgstr "" msgid "Change history: %s" msgstr "" -#. Translators: Model verbose name and instance representation, -#. suitable to be an item in a list. +#. Translators: Model verbose name and instance +#. representation, suitable to be an item in a +#. list. #, python-format msgid "%(class_name)s %(instance)s" msgstr "" @@ -226,111 +275,139 @@ msgid "" msgstr "" msgid "Django site admin" -msgstr "" +msgstr "जॅंगो स्थळ प्रशासक" msgid "Django administration" -msgstr "" +msgstr "जॅंगो प्रशासन " msgid "Site administration" -msgstr "" +msgstr "स्थळ प्रशासन " msgid "Log in" msgstr "" #, python-format msgid "%(app)s administration" -msgstr "" +msgstr "%(app)s प्रशासन" msgid "Page not found" -msgstr "" +msgstr "पान मिळाले नाही" -msgid "We're sorry, but the requested page could not be found." -msgstr "" +msgid "We’re sorry, but the requested page could not be found." +msgstr "आम्ही क्षमस्व आहोत, पण विनंती केलेले पान मिळाले नाही." msgid "Home" -msgstr "" +msgstr "मुख्यपान" msgid "Server error" -msgstr "" +msgstr "वाढप्यात त्रुटी" msgid "Server error (500)" -msgstr "" +msgstr "सर्व्हर त्रुटी (500)" msgid "Server Error (500)" -msgstr "" +msgstr "सर्व्हर त्रुटी (500)" msgid "" -"There's been an error. It's been reported to the site administrators via " +"There’s been an error. It’s been reported to the site administrators via " "email and should be fixed shortly. Thanks for your patience." msgstr "" +"त्रुटी आली आहे व ती विपत्राद्वारे सांकेतिकस्थळ व्यवस्थापकांकडे कळविण्यात आली आहे आणि लवकरच " +"ती सुधारली जाईल. आपल्या सहनशीलतेसाठी धन्यवाद." msgid "Run the selected action" -msgstr "" +msgstr "निवडलेली क्रिया चालवा" msgid "Go" -msgstr "" +msgstr "जा" msgid "Click here to select the objects across all pages" -msgstr "" +msgstr "पानावरील सर्व वस्तूंची निवड करण्यासाठी येथे टिचकी मारा" #, python-format msgid "Select all %(total_count)s %(module_name)s" -msgstr "" +msgstr "सर्व %(total_count)s %(module_name)s निवडा" msgid "Clear selection" +msgstr "निवड काढा" + +msgid "Breadcrumbs" +msgstr "ब्रेडक्रम्ब्स" + +#, python-format +msgid "Models in the %(name)s application" msgstr "" +msgid "Add" +msgstr "जोडा" + +msgid "View" +msgstr "पहा" + +msgid "You don’t have permission to view or edit anything." +msgstr "तुम्हाला काहीही पाहण्याची किंवा संपादित करण्याची परवानगी नाही." + msgid "" -"First, enter a username and password. Then, you'll be able to edit more user " +"First, enter a username and password. Then, you’ll be able to edit more user " "options." msgstr "" +"पहिलं, वापरकर्तानाव आणि गुप्तशब्द नमूद करा. मग, आपण अधिक वापरकर्ता पर्यायांचे संपादन करू " +"शकता." msgid "Enter a username and password." -msgstr "" +msgstr "वापरकर्तानाव आणि गुप्तशब्द नमूद करा." msgid "Change password" -msgstr "" +msgstr "गुप्तशब्द बदला" msgid "Please correct the error below." -msgstr "" - -msgid "Please correct the errors below." -msgstr "" +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" #, python-format msgid "Enter a new password for the user %(username)s." -msgstr "" +msgstr "%(username)s वापरकर्त्यासाठी नवीन गुप्तशब्द नमूद करा " + +msgid "Skip to main content" +msgstr "मुख्य सामुग्रीवर जा" msgid "Welcome," -msgstr "" +msgstr "स्वागत आहे," msgid "View site" -msgstr "" +msgstr "संकेतस्थळ पहा" msgid "Documentation" -msgstr "" +msgstr "दस्तऐवज" msgid "Log out" -msgstr "" +msgstr "बाहेर पडा" -msgid "Add" +#, python-format +msgid "Add %(name)s" msgstr "" msgid "History" -msgstr "" +msgstr "इतिहास" msgid "View on site" -msgstr "" - -#, python-format -msgid "Add %(name)s" -msgstr "" +msgstr "संकेतस्थळावर पहा" msgid "Filter" -msgstr "" +msgstr "गाळणी" + +msgid "Hide counts" +msgstr "गणना लपवा" + +msgid "Show counts" +msgstr "गणना दाखवा" + +msgid "Clear all filters" +msgstr "सर्व गाळण्या साफ करा" msgid "Remove from sorting" -msgstr "" +msgstr "सोडवा सोडवा" #, python-format msgid "Sorting priority: %(priority_number)s" @@ -339,8 +416,17 @@ msgstr "" msgid "Toggle sorting" msgstr "" +msgid "Toggle theme (current theme: auto)" +msgstr "थीम खुंटी बदला (सध्याची थीम: स्वयंप्रेरित)" + +msgid "Toggle theme (current theme: light)" +msgstr "थीम खुंटी बदला (सध्याची थीम: उजेड)" + +msgid "Toggle theme (current theme: dark)" +msgstr "थीम खुंटी बदला (सध्याची थीम: काळोख)" + msgid "Delete" -msgstr "" +msgstr "घालवा" #, python-format msgid "" @@ -360,18 +446,20 @@ msgid "" "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " "All of the following related items will be deleted:" msgstr "" +"\"%(escaped_object)s\" %(object_name)sनावाच्या वस्तू घालवताना त्याच्या संबंधित " +"वस्तूही घालवाव्या लागतील" msgid "Objects" msgstr "" -msgid "Yes, I'm sure" -msgstr "" +msgid "Yes, I’m sure" +msgstr "होय, मला खात्री आहे" msgid "No, take me back" -msgstr "" +msgstr "नको, मला मागे न्या" msgid "Delete multiple objects" -msgstr "" +msgstr "एकाधिक वस्तू घालवा" #, python-format msgid "" @@ -385,95 +473,111 @@ msgid "" "Deleting the selected %(objects_name)s would require deleting the following " "protected related objects:" msgstr "" +"निवडलेले %(objects_name)s घालवण्यासाठी खालील संरक्षित संबंधित वस्तू डिलीट करणे आवश्यक " +"आहे." #, python-format msgid "" "Are you sure you want to delete the selected %(objects_name)s? All of the " "following objects and their related items will be deleted:" msgstr "" - -msgid "Change" -msgstr "" - -msgid "Remove" -msgstr "" - -#, python-format -msgid "Add another %(verbose_name)s" -msgstr "" +"तुम्हाला खात्री आहे की तुम्ही निवडलेले %(objects_name)s हटवायला याची खात्री आहे का? " +"खात्री आहे की खालील वस्तूंचे आणि त्यांच्या संबंधित घटक हटवले जातील:" msgid "Delete?" -msgstr "" +msgstr "घालवायचं ?" #, python-format msgid " By %(filter_title)s " msgstr "" msgid "Summary" -msgstr "" +msgstr "सारांश" -#, python-format -msgid "Models in the %(name)s application" -msgstr "" +msgid "Recent actions" +msgstr "अलीकडच्या क्रिया" -msgid "You don't have permission to edit anything." -msgstr "" +msgid "My actions" +msgstr "माझ्या क्रिया" -msgid "Recent Actions" -msgstr "" +msgid "None available" +msgstr "काहीही उपलब्ध नाही" -msgid "My Actions" -msgstr "" +msgid "Added:" +msgstr "जोडले गेले:" -msgid "None available" -msgstr "" +msgid "Changed:" +msgstr "बदलले." + +msgid "Deleted:" +msgstr "घालवले." msgid "Unknown content" -msgstr "" +msgstr "अज्ञात सामुग्री" msgid "" -"Something's wrong with your database installation. Make sure the appropriate " +"Something’s wrong with your database installation. Make sure the appropriate " "database tables have been created, and make sure the database is readable by " "the appropriate user." msgstr "" +"तुमच्या माहितीगठ्ठा स्थापनेत काहीतरी चुक आहे. खात्री करा की योग्य डेटाबेस तक्ते तयार केलेले " +"आहेत आणि खात्री करा की योग्य वापरकर्त्या माहितीगठ्ठा वाचू शकतो." + +#, python-format +msgid "" +"You are authenticated as %(username)s, but are not authorized to access this " +"page. Would you like to login to a different account?" +msgstr "" +"तुम्ही %(username)s म्हणून प्रमाणित केले आहे, परंतु हे पानात शिरकाव करण्यास अधिकृत नाही. " +"तुम्हाला वेगळ्या खात्यात प्रवेश करायला आवडेल का?" msgid "Forgotten your password or username?" +msgstr "तुमचा गुप्तशब्द किंवा वापरकर्तानाव विसरलात का?" + +msgid "Toggle navigation" +msgstr "टॉगल नेविगेशन" + +msgid "Sidebar" +msgstr "बाजूभिंत" + +msgid "Start typing to filter…" +msgstr "प्रविष्ट करण्यासाठी टाइप करण्याची सुरुवात करा ..." + +msgid "Filter navigation items" msgstr "" msgid "Date/time" -msgstr "" +msgstr "दिनांक/वेळ" msgid "User" -msgstr "" +msgstr "वापरकर्ता" msgid "Action" -msgstr "" +msgstr "क्रिया" + +msgid "entry" +msgid_plural "entries" +msgstr[0] "" +msgstr[1] "" msgid "" -"This object doesn't have a change history. It probably wasn't added via this " +"This object doesn’t have a change history. It probably wasn’t added via this " "admin site." msgstr "" +"या वस्तूचा कोणताही बदलाचा इतिहास नाही. कदाचित तो व्यवस्थापक मार्गे नव्हता जोडला गेला " +"असावा." msgid "Show all" -msgstr "" +msgstr "सर्व दाखवा" msgid "Save" -msgstr "" +msgstr "साठवा" -#, python-format -msgid "Change selected %(model)s" -msgstr "" - -#, python-format -msgid "Add another %(model)s" -msgstr "" - -#, python-format -msgid "Delete selected %(model)s" -msgstr "" +msgid "Popup closing…" +msgstr "पॉपअप बंद होत आहे..." msgid "Search" -msgstr "" +msgstr "शोधा" #, python-format msgid "%(counter)s result" @@ -486,124 +590,164 @@ msgid "%(full_result_count)s total" msgstr "" msgid "Save as new" -msgstr "" +msgstr "नवीन म्हणून साठवा" msgid "Save and add another" -msgstr "" +msgstr "साठवा आणि आणखी एक जोडा" msgid "Save and continue editing" -msgstr "" +msgstr "साठवा आणि संपादन सुरू ठेवा" -msgid "Thanks for spending some quality time with the Web site today." -msgstr "" +msgid "Save and view" +msgstr "साठवा आणि पहा" + +msgid "Close" +msgstr "बंद" + +#, python-format +msgid "Change selected %(model)s" +msgstr "निवडलेले %(model)s बदला" + +#, python-format +msgid "Add another %(model)s" +msgstr "अजून एक %(model)s जोडा" + +#, python-format +msgid "Delete selected %(model)s" +msgstr "निवडलेले %(model)s घालवा" + +#, python-format +msgid "View selected %(model)s" +msgstr "निवडलेले %(model)s पहा" + +msgid "Thanks for spending some quality time with the web site today." +msgstr "आज संकेतस्थळावर अमुल्य वेळ घालवल्याबद्दल धन्यवाद." msgid "Log in again" -msgstr "" +msgstr "पुन्हा प्रवेश करा" msgid "Password change" -msgstr "" +msgstr "गुप्तशब्द बदला" msgid "Your password was changed." -msgstr "" +msgstr "तुमचा गुप्तशब्द बदलला गेला आहे." msgid "" -"Please enter your old password, for security's sake, and then enter your new " +"Please enter your old password, for security’s sake, and then enter your new " "password twice so we can verify you typed it in correctly." msgstr "" +"सुरक्षेसाठी कृपया आपला जुना गुप्तशब्द नमूद करा, आणि नंतर आपला नवीन गुप्तशब्द दोनदा नमूद " +"करा जेणेकरून तुम्ही गुप्तशब्द अचूक नमूद केला आहे की नाही ह्याची आम्ही पडताळणी करू." msgid "Change my password" -msgstr "" +msgstr "माझा गुप्तशब्द बदला" msgid "Password reset" -msgstr "" +msgstr "गुप्तशब्द पुन्हस्थापना" msgid "Your password has been set. You may go ahead and log in now." -msgstr "" +msgstr "तुमचा गुप्तशब्द जोडला आहे. आपण आता प्रवेश करू शकता." msgid "Password reset confirmation" -msgstr "" +msgstr "गुप्तशब्द पुन्हस्थापना निश्चित" msgid "" "Please enter your new password twice so we can verify you typed it in " "correctly." msgstr "" +"कृपया आपला नवीन गुप्तशब्द दोनदा नमूद करा, जेणेकरून तुम्ही तो योग्य नमूद केला आहे का याची " +"आम्ही पडताळणी करू." msgid "New password:" -msgstr "" +msgstr "नवीन गुप्तशब्द:" msgid "Confirm password:" -msgstr "" +msgstr "निश्चित गुप्तशब्द:" msgid "" "The password reset link was invalid, possibly because it has already been " "used. Please request a new password reset." msgstr "" +"गुप्तशब्द पुन्हस्थापना दुवा अवैध आहे, कदाचित तो आधीच वापरला गेलेला आहे. कृपया नवीन गुप्तशब्द " +"पुन्हस्थापनेची विनंती करा." msgid "" -"We've emailed you instructions for setting your password, if an account " +"We’ve emailed you instructions for setting your password, if an account " "exists with the email you entered. You should receive them shortly." msgstr "" +"आपल्याला आपला गुप्तशब्द पुन्हस्थापीत करण्याच्या सूचना विपत्र केल्या आहेत, जर नमूद केलेल्या " +"विपत्रासह खाते उपलब्ध असेल तर आपल्याला ते लवकरच मिळायला पाहीजे." msgid "" -"If you don't receive an email, please make sure you've entered the address " +"If you don’t receive an email, please make sure you’ve entered the address " "you registered with, and check your spam folder." msgstr "" +"जर तुम्हाला विपत्र मिळत नसेल तर कृपया खाते नोंदवलेला विपत्र तुम्ही योग्य नमूद केलाय का " +"याची खात्री करा आणि तुमचा स्पॅम फोल्डर तपासा." #, python-format msgid "" "You're receiving this email because you requested a password reset for your " "user account at %(site_name)s." msgstr "" +"तुम्हाला हा विपत्र मिळत आहे कारण तुम्ही %(site_name)s या संकेतस्थळावरील तुमच्या " +"वापरकर्ता खात्यासाठी गुप्तशब्द पुन्हस्थापनेची विनंती केली होती." msgid "Please go to the following page and choose a new password:" -msgstr "" +msgstr "कृपया खालील पानावर जा आणि नवीन गुप्तशब्द निवडा." -msgid "Your username, in case you've forgotten:" -msgstr "" +msgid "Your username, in case you’ve forgotten:" +msgstr "तुमचे वापरकर्तानाव, जर तुम्ही विसरला असाल तर:" msgid "Thanks for using our site!" -msgstr "" +msgstr "आमच्या संकेतस्थळाचा वापर केल्याबद्दल आभार!" #, python-format msgid "The %(site_name)s team" -msgstr "" +msgstr "%(site_name)s संघ" msgid "" -"Forgotten your password? Enter your email address below, and we'll email " +"Forgotten your password? Enter your email address below, and we’ll email " "instructions for setting a new one." msgstr "" +"तुमचा गुप्तशब्द विसरलात का? तुमचा विपत्रपत्ता खाली नमूद करा. नवीन गुप्तशब्द " +"ठरवण्यासाठीच्या सूचना आम्ही तुम्हाला विपत्र करू." msgid "Email address:" -msgstr "" +msgstr "विपत्र पत्ता:" msgid "Reset my password" -msgstr "" +msgstr "माझा गुप्तशब्द पुन्हस्थापन करा" -msgid "All dates" -msgstr "" +msgid "Select all objects on this page for an action" +msgstr "क्रिया करण्यासाठी या पानावरील सर्व घटक निवडा." -msgid "(None)" -msgstr "" +msgid "All dates" +msgstr "सर्व दिनांक" #, python-format msgid "Select %s" -msgstr "" +msgstr "%s निवडा" #, python-format msgid "Select %s to change" -msgstr "" +msgstr "बदलण्यासाठी %s निवडा" + +#, python-format +msgid "Select %s to view" +msgstr "पाहण्यासाठी %s निवडा" msgid "Date:" -msgstr "" +msgstr "दिनांक:" msgid "Time:" -msgstr "" +msgstr "वेळ:" msgid "Lookup" -msgstr "" +msgstr "शोध" msgid "Currently:" -msgstr "" +msgstr "सध्या:" msgid "Change:" -msgstr "" +msgstr "बदला:" diff --git a/django/contrib/admin/locale/sw/LC_MESSAGES/django.mo b/django/contrib/admin/locale/sw/LC_MESSAGES/django.mo index a66e246dcd8..9aa7f311c2d 100644 Binary files a/django/contrib/admin/locale/sw/LC_MESSAGES/django.mo and b/django/contrib/admin/locale/sw/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admin/locale/sw/LC_MESSAGES/django.po b/django/contrib/admin/locale/sw/LC_MESSAGES/django.po index a2eb18c0fd9..afbca8e7f47 100644 --- a/django/contrib/admin/locale/sw/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/sw/LC_MESSAGES/django.po @@ -2,6 +2,7 @@ # # Translators: # Antony Owino , 2023 +# DOREEN WANYAMA, 2023 # Machaku, 2013-2014 # Machaku, 2016 # Millicent Atieno Obwanda , 2023 @@ -11,8 +12,8 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Natalia (Django Fellow), 2023\n" +"PO-Revision-Date: 2023-12-25 07:05+0000\n" +"Last-Translator: DOREEN WANYAMA, 2023\n" "Language-Team: Swahili (http://app.transifex.com/django/django/language/" "sw/)\n" "MIME-Version: 1.0\n" @@ -250,7 +251,7 @@ msgstr "Badilisha %s" #, python-format msgid "View %s" -msgstr "" +msgstr "Muonekano %s" msgid "Database error" msgstr "Hitilafu katika hifadhidata" @@ -358,7 +359,7 @@ msgid "Add" msgstr "Ongeza" msgid "View" -msgstr "" +msgstr "Muonekano" msgid "You don’t have permission to view or edit anything." msgstr "Huna ruhusa ya kutazama au kuhariri kitu chochote" @@ -378,8 +379,8 @@ msgstr "Badilisha nywila" msgid "Please correct the error below." msgid_plural "Please correct the errors below." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Tafadhali sahihisha kosa lifuatalo." +msgstr[1] "Tafadhali sahihisha makosa yafuatayo" #, python-format msgid "Enter a new password for the user %(username)s." @@ -582,8 +583,8 @@ msgstr "Tendo" msgid "entry" msgid_plural "entries" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "ingizo" +msgstr[1] "maingizo" msgid "" "This object doesn’t have a change history. It probably wasn’t added via this " diff --git a/django/contrib/admin/locale/uz/LC_MESSAGES/django.mo b/django/contrib/admin/locale/uz/LC_MESSAGES/django.mo index 67c6d07e41c..253820c477e 100644 Binary files a/django/contrib/admin/locale/uz/LC_MESSAGES/django.mo and b/django/contrib/admin/locale/uz/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admin/locale/uz/LC_MESSAGES/django.po b/django/contrib/admin/locale/uz/LC_MESSAGES/django.po index 80dd7971a64..8b4f8fd6b8e 100644 --- a/django/contrib/admin/locale/uz/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/uz/LC_MESSAGES/django.po @@ -6,17 +6,17 @@ # Bedilbek Khamidov , 2019 # Claude Paroz , 2019 # Nuriddin Islamov, 2021 -# Shukrullo Turgunov , 2021 +# Shukrullo Turgunov , 2021,2024 # Sukhrobbek Ismatov , 2019 # Yet Sum , 2019 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-09-21 10:22+0200\n" -"PO-Revision-Date: 2021-12-16 12:06+0000\n" -"Last-Translator: Alex Ibragimov\n" -"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-01-25 07:05+0000\n" +"Last-Translator: Shukrullo Turgunov , 2021,2024\n" +"Language-Team: Uzbek (http://app.transifex.com/django/django/language/uz/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -25,7 +25,7 @@ msgstr "" #, python-format msgid "Delete selected %(verbose_name_plural)s" -msgstr "%(verbose_name_plural)s tanlanganlarni o'chirish" +msgstr "%(verbose_name_plural)s larni o'chirish" #, python-format msgid "Successfully deleted %(count)d %(items)s." @@ -42,7 +42,7 @@ msgid "Administration" msgstr "Administratsiya" msgid "All" -msgstr "Hammasi" +msgstr "Barchasi" msgid "Yes" msgstr "Ha" @@ -96,7 +96,7 @@ msgid "Add another %(verbose_name)s" msgstr "Boshqa %(verbose_name)s qo‘shish" msgid "Remove" -msgstr "Olib tashlash" +msgstr "O'chirish" msgid "Addition" msgstr " Qo'shish" @@ -182,6 +182,9 @@ msgstr "Bo'sh" msgid "Hold down “Control”, or “Command” on a Mac, to select more than one." msgstr "" +msgid "Select this object for an action - {}" +msgstr "" + #, python-brace-format msgid "The {name} “{obj}” was added successfully." msgstr "" @@ -262,8 +265,9 @@ msgstr "" msgid "Change history: %s" msgstr "" -#. Translators: Model verbose name and instance representation, -#. suitable to be an item in a list. +#. Translators: Model verbose name and instance +#. representation, suitable to be an item in a +#. list. #, python-format msgid "%(class_name)s %(instance)s" msgstr "" @@ -329,6 +333,9 @@ msgstr "" msgid "Clear selection" msgstr "" +msgid "Breadcrumbs" +msgstr "" + #, python-format msgid "Models in the %(name)s application" msgstr "" @@ -354,15 +361,16 @@ msgid "Change password" msgstr "Parolni o'zgartirish" msgid "Please correct the error below." -msgstr "" - -msgid "Please correct the errors below." -msgstr "" +msgid_plural "Please correct the errors below." +msgstr[0] "" #, python-format msgid "Enter a new password for the user %(username)s." msgstr "" +msgid "Skip to main content" +msgstr "" + msgid "Welcome," msgstr "Xush kelibsiz," @@ -388,6 +396,12 @@ msgstr "Saytda ko'rish" msgid "Filter" msgstr "Saralash" +msgid "Hide counts" +msgstr "" + +msgid "Show counts" +msgstr "" + msgid "Clear all filters" msgstr "" @@ -401,6 +415,15 @@ msgstr "" msgid "Toggle sorting" msgstr "" +msgid "Toggle theme (current theme: auto)" +msgstr "" + +msgid "Toggle theme (current theme: light)" +msgstr "" + +msgid "Toggle theme (current theme: dark)" +msgstr "" + msgid "Delete" msgstr "O'chirish" @@ -473,6 +496,15 @@ msgstr "Mening harakatlarim" msgid "None available" msgstr "" +msgid "Added:" +msgstr "" + +msgid "Changed:" +msgstr "" + +msgid "Deleted:" +msgstr "" + msgid "Unknown content" msgstr "" @@ -494,6 +526,9 @@ msgstr "" msgid "Toggle navigation" msgstr "Navigatsiyani almashtirish" +msgid "Sidebar" +msgstr "" + msgid "Start typing to filter…" msgstr "" @@ -509,6 +544,10 @@ msgstr "" msgid "Action" msgstr "" +msgid "entry" +msgid_plural "entries" +msgstr[0] "" + msgid "" "This object doesn’t have a change history. It probably wasn’t added via this " "admin site." @@ -562,6 +601,10 @@ msgstr "" msgid "Delete selected %(model)s" msgstr "" +#, python-format +msgid "View selected %(model)s" +msgstr "" + msgid "Thanks for spending some quality time with the web site today." msgstr "" @@ -647,6 +690,9 @@ msgstr "" msgid "Reset my password" msgstr "Parolimni tiklash" +msgid "Select all objects on this page for an action" +msgstr "" + msgid "All dates" msgstr "Barcha sanalar" diff --git a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.mo b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.mo index af501d2aa86..4bee1a8d452 100644 Binary files a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.mo and b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.po b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.po index f8c329dde8c..abc545310cc 100644 --- a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.po @@ -5,6 +5,7 @@ # Brian Wang , 2018 # Fulong Sun , 2016 # Huanqun Yang, 2022 +# jack yang, 2023 # Jannis Leidel , 2011 # Kevin Sze , 2012 # Lele Long , 2011,2015 @@ -34,8 +35,8 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Scott Jiang, 2023\n" +"PO-Revision-Date: 2023-12-25 07:05+0000\n" +"Last-Translator: jack yang, 2023\n" "Language-Team: Chinese (China) (http://app.transifex.com/django/django/" "language/zh_CN/)\n" "MIME-Version: 1.0\n" @@ -203,7 +204,7 @@ msgid "Hold down “Control”, or “Command” on a Mac, to select more than o msgstr "按住 Control 键或 Mac 上的 Command 键来选择多项。" msgid "Select this object for an action - {}" -msgstr "" +msgstr "选择此对象执行操作 - {}" #, python-brace-format msgid "The {name} “{obj}” was added successfully." @@ -421,10 +422,10 @@ msgid "Filter" msgstr "过滤器" msgid "Hide counts" -msgstr "" +msgstr "隐藏计数" msgid "Show counts" -msgstr "" +msgstr "显示计数" msgid "Clear all filters" msgstr "清除所有筛选" @@ -507,7 +508,7 @@ msgid "" "Are you sure you want to delete the selected %(objects_name)s? All of the " "following objects and their related items will be deleted:" msgstr "" -"请确认要删除选中的 %(objects_name)s 吗?以下所有对象和余它们相关的条目将都会" +"请确认要删除选中的 %(objects_name)s 吗?以下所有对象和与它们相关的条目将都会" "被删除:" msgid "Delete?" @@ -530,13 +531,13 @@ msgid "None available" msgstr "无可选的" msgid "Added:" -msgstr "" +msgstr "已添加:" msgid "Changed:" -msgstr "" +msgstr "已修改:" msgid "Deleted:" -msgstr "" +msgstr "已删除:" msgid "Unknown content" msgstr "未知内容" @@ -734,7 +735,7 @@ msgid "Reset my password" msgstr "重设我的密码" msgid "Select all objects on this page for an action" -msgstr "" +msgstr "选择此页面上的所有对象执行操作" msgid "All dates" msgstr "所有日期" diff --git a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.mo b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.mo index 255ea4a11b4..c78566a8767 100644 Binary files a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.mo and b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.mo differ diff --git a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.po b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.po index ed1f0b744f5..44f47c8b391 100644 --- a/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.po +++ b/django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.po @@ -3,6 +3,7 @@ # Translators: # HuanCheng Bai白宦成(Bestony) , 2018 # Fan Xu , 2022 +# jack yang, 2023 # Jannis Leidel , 2011 # Kaiqi Zhu, 2023 # Kewei Ma , 2016 @@ -21,8 +22,8 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-18 15:04-0300\n" -"PO-Revision-Date: 2023-12-04 07:59+0000\n" -"Last-Translator: Kaiqi Zhu, 2023\n" +"PO-Revision-Date: 2023-12-25 07:59+0000\n" +"Last-Translator: jack yang, 2023\n" "Language-Team: Chinese (China) (http://app.transifex.com/django/django/" "language/zh_CN/)\n" "MIME-Version: 1.0\n" @@ -248,53 +249,53 @@ msgid "Dec" msgstr "十二月" msgid "Sunday" -msgstr "" +msgstr "星期日" msgid "Monday" -msgstr "" +msgstr "星期一" msgid "Tuesday" -msgstr "" +msgstr "星期二" msgid "Wednesday" -msgstr "" +msgstr "星期三" msgid "Thursday" -msgstr "" +msgstr "星期四" msgid "Friday" -msgstr "" +msgstr "星期五" msgid "Saturday" -msgstr "" +msgstr "星期六" msgctxt "abbrev. day Sunday" msgid "Sun" -msgstr "" +msgstr "星期日" msgctxt "abbrev. day Monday" msgid "Mon" -msgstr "" +msgstr "星期一" msgctxt "abbrev. day Tuesday" msgid "Tue" -msgstr "" +msgstr "星期二" msgctxt "abbrev. day Wednesday" msgid "Wed" -msgstr "" +msgstr "星期三" msgctxt "abbrev. day Thursday" msgid "Thur" -msgstr "" +msgstr "星期四" msgctxt "abbrev. day Friday" msgid "Fri" -msgstr "" +msgstr "星期五" msgctxt "abbrev. day Saturday" msgid "Sat" -msgstr "" +msgstr "星期六" msgctxt "one letter Sunday" msgid "S" diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 33d55408b06..6f0bda46380 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -465,31 +465,32 @@ def lookup_allowed(self, lookup, value, request=None): relation_parts = [] prev_field = None - for part in lookup.split(LOOKUP_SEP): + parts = lookup.split(LOOKUP_SEP) + for part in parts: try: field = model._meta.get_field(part) except FieldDoesNotExist: # Lookups on nonexistent fields are ok, since they're ignored # later. break - if not prev_field or ( - prev_field.is_relation - and field not in model._meta.parents.values() - and field is not model._meta.auto_field - and ( - model._meta.auto_field is None - or part not in getattr(prev_field, "to_fields", []) - ) - ): - relation_parts.append(part) if not getattr(field, "path_infos", None): # This is not a relational field, so further parts # must be transforms. break + if ( + not prev_field + or (field.is_relation and field not in model._meta.parents.values()) + or ( + prev_field.is_relation + and model._meta.auto_field is None + and part not in getattr(prev_field, "to_fields", []) + ) + ): + relation_parts.append(part) prev_field = field model = field.path_infos[-1].to_opts.model - if len(relation_parts) <= 1: + if not relation_parts or len(parts) == 1: # Either a local field filter, or no fields at all. return True valid_lookups = {self.date_hierarchy} @@ -1747,9 +1748,9 @@ def get_inline_formsets(self, request, formsets, inline_instances, obj=None): has_delete_permission = inline.has_delete_permission(request, obj) else: # Disable all edit-permissions, and override formset settings. - has_add_permission = ( - has_change_permission - ) = has_delete_permission = False + has_add_permission = has_change_permission = has_delete_permission = ( + False + ) formset.extra = formset.max_num = 0 has_view_permission = inline.has_view_permission(request, obj) prepopulated = dict(inline.get_prepopulated_fields(request, obj)) @@ -1884,9 +1885,11 @@ def _changeform_view(self, request, object_id, form_url, extra_context): form, list(fieldsets), # Clear prepopulated fields on a view-only form to avoid a crash. - self.get_prepopulated_fields(request, obj) - if add or self.has_change_permission(request, obj) - else {}, + ( + self.get_prepopulated_fields(request, obj) + if add or self.has_change_permission(request, obj) + else {} + ), readonly_fields, model_admin=self, ) diff --git a/django/contrib/admin/static/admin/css/base.css b/django/contrib/admin/static/admin/css/base.css index 8a2837a55dd..44f2fc8802e 100644 --- a/django/contrib/admin/static/admin/css/base.css +++ b/django/contrib/admin/static/admin/css/base.css @@ -102,7 +102,7 @@ body { /* LINKS */ a:link, a:visited { - color: var(--body-fg); + color: var(--link-fg); text-decoration: none; transition: color 0.15s, background 0.15s; } diff --git a/django/contrib/admin/static/admin/css/forms.css b/django/contrib/admin/static/admin/css/forms.css index 6cfe9da1194..9a8dad08cce 100644 --- a/django/contrib/admin/static/admin/css/forms.css +++ b/django/contrib/admin/static/admin/css/forms.css @@ -26,6 +26,10 @@ form .form-row p { display: flex; } +.form-multiline { + flex-wrap: wrap; +} + .form-multiline > div { padding-bottom: 10px; } diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 2dcdf62afb2..0c32290b6ca 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -171,9 +171,9 @@ def make_qs_param(t, n): "url_primary": cl.get_query_string({ORDER_VAR: ".".join(o_list_primary)}), "url_remove": cl.get_query_string({ORDER_VAR: ".".join(o_list_remove)}), "url_toggle": cl.get_query_string({ORDER_VAR: ".".join(o_list_toggle)}), - "class_attrib": format_html(' class="{}"', " ".join(th_classes)) - if th_classes - else "", + "class_attrib": ( + format_html(' class="{}"', " ".join(th_classes)) if th_classes else "" + ), } @@ -270,9 +270,11 @@ def link_in_col(is_first, field_name, cl): link_or_text = format_html( '{}', url, - format_html(' data-popup-opener="{}"', value) - if cl.is_popup - else "", + ( + format_html(' data-popup-opener="{}"', value) + if cl.is_popup + else "" + ), result_repr, ) diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py index fc0cd941d12..ca844cddb39 100644 --- a/django/contrib/admin/widgets.py +++ b/django/contrib/admin/widgets.py @@ -1,6 +1,7 @@ """ Form Widget classes specific to the Django admin site. """ + import copy import json diff --git a/django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo b/django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo index 43410e7ab73..30b84dab60f 100644 Binary files a/django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo and b/django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admindocs/locale/af/LC_MESSAGES/django.po b/django/contrib/admindocs/locale/af/LC_MESSAGES/django.po index 6074aa0551f..4053b8b9fac 100644 --- a/django/contrib/admindocs/locale/af/LC_MESSAGES/django.po +++ b/django/contrib/admindocs/locale/af/LC_MESSAGES/django.po @@ -64,13 +64,16 @@ msgid "" msgstr "" msgid "Models" -msgstr "" +msgstr "Modelle" msgid "" "Models are descriptions of all the objects in the system and their " "associated fields. Each model has a list of fields which can be accessed as " "template variables" msgstr "" +"Modelle is beskrywings van al die objekte in die stelsel met hulle velde. " +"Elke model het 'n lys velde wat bereikbaar is as veranderlikes in 'n " +"sjabloon." msgid "Views" msgstr "" @@ -107,7 +110,7 @@ msgstr "" #, python-format msgid "Model: %(name)s" -msgstr "" +msgstr "Model: %(name)s" msgid "Fields" msgstr "Velde" @@ -202,10 +205,10 @@ msgid "Templates:" msgstr "" msgid "Back to View documentation" -msgstr "" +msgstr "Terug na Sien dokumentasie" msgid "View documentation" -msgstr "" +msgstr "Sien dokumentasie" msgid "Jump to namespace" msgstr "" diff --git a/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo b/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo index 7d0ec6a16ac..4b9b343ae12 100644 Binary files a/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo and b/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo differ diff --git a/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po b/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po index e4e4b0caf8a..54de5cfc683 100644 --- a/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po +++ b/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po @@ -4,17 +4,18 @@ # Bayarkhuu Bataa, 2014 # Claude Paroz , 2014 # Jannis Leidel , 2011 -# Zorig , 2013-2014,2016-2017 +# Turmunkh Batkhuyag, 2023 +# Zorig, 2013-2014,2016-2017 # Анхбаяр Анхаа , 2014-2015 # Баясгалан Цэвлээ , 2015 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-01-19 16:49+0100\n" -"PO-Revision-Date: 2017-09-19 16:40+0000\n" -"Last-Translator: Zorig \n" -"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-24 20:19+0000\n" +"Last-Translator: Turmunkh Batkhuyag, 2023\n" +"Language-Team: Mongolian (http://app.transifex.com/django/django/language/" "mn/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -23,19 +24,19 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Administrative Documentation" -msgstr "Удирдлагын баримт" +msgstr "Удирдлагын баримт бичиг" msgid "Home" -msgstr "Админ эхлэл" +msgstr "Нүүр" msgid "Documentation" -msgstr "Баримтжуулалт" +msgstr "Баримт бичиг" msgid "Bookmarklets" -msgstr "Bookmarklet-ууд" +msgstr "Хавчуурга" msgid "Documentation bookmarklets" -msgstr "Мookmarklet-уудын баримтжуулалт" +msgstr "Баримт бичгийн хавчуурга" msgid "" "To install bookmarklets, drag the link to your bookmarks toolbar, or right-" @@ -102,11 +103,9 @@ msgstr "docutils ийг суулгана уу" #, python-format msgid "" -"The admin documentation system requires Python's docutils library." +"The admin documentation system requires Python’s docutils library." msgstr "" -"Админ хэсгийн баримтжуулалтын ажиллуулхад Python ийн docutils санг суулгах шаардлагатай." #, python-format msgid "" @@ -157,13 +156,13 @@ msgid "Template: %(name)s" msgstr "Загвар: %(name)s" #, python-format -msgid "Template: \"%(name)s\"" -msgstr "Загвар: \"%(name)s\"" +msgid "Template: %(name)s" +msgstr "" #. Translators: Search is not a verb here, it qualifies path (a search path) #, python-format -msgid "Search path for template \"%(name)s\":" -msgstr "\"%(name)s\" тэмплэйтын зам хайх" +msgid "Search path for template %(name)s:" +msgstr "" msgid "(does not exist)" msgstr "(Оршдоггүй)" diff --git a/django/contrib/auth/base_user.py b/django/contrib/auth/base_user.py index da0eac731fb..386584b2731 100644 --- a/django/contrib/auth/base_user.py +++ b/django/contrib/auth/base_user.py @@ -2,6 +2,7 @@ This module allows importing AbstractBaseUser even when django.contrib.auth is not in INSTALLED_APPS. """ + import unicodedata import warnings diff --git a/django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo b/django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo index 588aaa840f2..9814f3295a7 100644 Binary files a/django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo and b/django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/django/contrib/auth/locale/ckb/LC_MESSAGES/django.po b/django/contrib/auth/locale/ckb/LC_MESSAGES/django.po index 1fc0bb34537..30e02c1819f 100644 --- a/django/contrib/auth/locale/ckb/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/ckb/LC_MESSAGES/django.po @@ -1,15 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Swara , 2022 +# Swara , 2022,2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-04-25 08:09+0000\n" -"Last-Translator: Swara , 2022\n" -"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"PO-Revision-Date: 2024-01-25 08:09+0000\n" +"Last-Translator: Swara , 2022,2024\n" +"Language-Team: Central Kurdish (http://app.transifex.com/django/django/" "language/ckb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -271,6 +271,8 @@ msgid "" "Enter a valid username. This value may contain only unaccented lowercase a-z " "and uppercase A-Z letters, numbers, and @/./+/-/_ characters." msgstr "" +"ناوی بەکارهێنەرێکی دروست بنوسە. ئەم بەهایە لەوانەیە تەنها پیتی بچووکی بێ " +"زاراوەی تێدابێت a-z و پیتی گەورە A-Z، ژمارەکان، و هێماکانی @/./+/-/_." msgid "" "Enter a valid username. This value may contain only letters, numbers, and " diff --git a/django/contrib/auth/locale/mr/LC_MESSAGES/django.mo b/django/contrib/auth/locale/mr/LC_MESSAGES/django.mo index f33dd236cb2..84eef503a35 100644 Binary files a/django/contrib/auth/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/auth/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/auth/locale/mr/LC_MESSAGES/django.po b/django/contrib/auth/locale/mr/LC_MESSAGES/django.po index 16b3e278b4b..fa7b7f7b640 100644 --- a/django/contrib/auth/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-03-18 09:16+0100\n" -"PO-Revision-Date: 2015-03-18 10:30+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2024-01-25 08:09+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,84 +18,93 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Personal info" -msgstr "" +msgstr "वैयक्तिक माहिती" msgid "Permissions" -msgstr "" +msgstr "परवानगी" msgid "Important dates" -msgstr "" +msgstr "महत्वाच्या दिनांक" #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "" msgid "Password changed successfully." -msgstr "" +msgstr "गुप्तशब्द यशस्वीरीत्या बदलला." #, python-format msgid "Change password: %s" -msgstr "" +msgstr "गुप्तशब्द बदला: %s" msgid "Authentication and Authorization" -msgstr "" +msgstr "प्रमाणीकरण आणि अधिकृतता" + +msgid "password" +msgstr "गुप्तशब्द" + +msgid "last login" +msgstr "शेवटचा प्रवेश" msgid "No password set." -msgstr "" +msgstr "कोणताही गुप्तशब्द सेट केलेला नाही." msgid "Invalid password format or unknown hashing algorithm." -msgstr "" +msgstr "अयोग्य गुप्तशब्द स्वरूप किंवा अज्ञात हॅशिंग अलगोरीथम." -msgid "The two password fields didn't match." -msgstr "" +msgid "The two password fields didn’t match." +msgstr "दोन गुप्तशब्द क्षेत्र जुळत नाहीत." msgid "Password" -msgstr "" +msgstr "गुप्तशब्द" msgid "Password confirmation" -msgstr "" +msgstr "गुप्तशब्द निच्छितीकरण" -msgid "Enter the same password as above, for verification." -msgstr "" +msgid "Enter the same password as before, for verification." +msgstr "पडताळणीसाठी आधीच्या गुप्तशब्दासारखा समान गुप्तशब्द नमूद करा." msgid "" -"Raw passwords are not stored, so there is no way to see this user's " -"password, but you can change the password using this " -"form." +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." msgstr "" +"कच्चे गुप्तशब्द साठवले जात नाहीत, त्यामुळे या वापरकर्त्याचा गुप्तशब्द पाहण्याचा कोणताही " +"मार्ग नाही, परंतु तुम्ही हा फॉर्म वापरून गुप्तशब्द बदलू शकता. " #, python-format msgid "" "Please enter a correct %(username)s and password. Note that both fields may " "be case-sensitive." msgstr "" +"कृपया करून एक योग्य %(username)s आणि गुप्तशब्द नमूद करा. लक्षात घ्या की दोन्ही रखाणे " +"संवेदनशील असू शकतात." msgid "This account is inactive." -msgstr "" +msgstr "हे खाते निष्क्रिय आहे." msgid "Email" -msgstr "" +msgstr "विपत्र" msgid "New password" -msgstr "" +msgstr "नवीन गुप्तशब्द" msgid "New password confirmation" -msgstr "" +msgstr "नवीन गुप्तशब्द निच्छितीकरण" msgid "Your old password was entered incorrectly. Please enter it again." -msgstr "" +msgstr "तुम्ही जुना गुप्तशब्द चुकीचा टाकला होता. कृपया तो पुन्हा नमूद करा." msgid "Old password" -msgstr "" +msgstr "जुना गुप्तशब्द" msgid "Password (again)" -msgstr "" +msgstr "गुप्तशब्द (पुन्हा)" msgid "algorithm" -msgstr "" +msgstr "अल्गोरिदम" msgid "iterations" -msgstr "" +msgstr "पुनरावृत्ती" msgid "salt" msgstr "" @@ -102,125 +112,188 @@ msgstr "" msgid "hash" msgstr "" +msgid "variety" +msgstr "निरनिराळ्या" + +msgid "version" +msgstr "आवृत्ती" + +msgid "memory cost" +msgstr "स्मरणशक्ती खर्च" + +msgid "time cost" +msgstr "वेळ खर्च" + +msgid "parallelism" +msgstr "समांतरता" + msgid "work factor" -msgstr "" +msgstr "कामाचा घटक" msgid "checksum" -msgstr "" +msgstr "चेकसम" + +msgid "block size" +msgstr "ब्लॉक आकार" msgid "name" -msgstr "" +msgstr "नाव" + +msgid "content type" +msgstr "सामुग्री प्रकार" msgid "codename" -msgstr "" +msgstr "सांकेतिक नाव" msgid "permission" -msgstr "" +msgstr "परवानगी" msgid "permissions" -msgstr "" +msgstr "परवानग्या" msgid "group" -msgstr "" +msgstr "समूह" msgid "groups" -msgstr "" - -msgid "password" -msgstr "" - -msgid "last login" -msgstr "" +msgstr "समूहं" msgid "superuser status" -msgstr "" +msgstr "सुपरयूजर स्थिती" msgid "" "Designates that this user has all permissions without explicitly assigning " "them." -msgstr "" +msgstr "या वापरकर्त्याकडे स्पष्टपणे नियुक्त केल्याशिवाय सर्व परवानग्या आहेत असे नियुक्त करते." msgid "" "The groups this user belongs to. A user will get all permissions granted to " "each of their groups." msgstr "" +"हा वापरकर्ता त्या गटांचा आहे. वापरकर्त्याला त्यांच्या प्रत्येक गटासाठी सर्व परवानग्या " +"मिळतील." msgid "user permissions" -msgstr "" +msgstr "वापरकर्ता परवानग्या" msgid "Specific permissions for this user." -msgstr "" +msgstr "या वापरकर्त्यासाठी विशिष्ट परवानग्या." msgid "username" -msgstr "" +msgstr "वापरकर्तानाव" -msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." -msgstr "" - -msgid "" -"Enter a valid username. This value may contain only letters, numbers and @/./" -"+/-/_ characters." -msgstr "" +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "आवश्यक. 150 किंवा कमी वर्ण. अक्षरे, अंक आणि @/./+/-/_ फक्त. " msgid "A user with that username already exists." -msgstr "" +msgstr "त्या वापरकर्ता नावासह वापरकर्ता आधीपासूनच अस्तित्वात आहे." msgid "first name" -msgstr "" +msgstr "पहिले नाव" msgid "last name" -msgstr "" +msgstr "आडनाव" msgid "email address" -msgstr "" +msgstr "विपत्र पत्ता" msgid "staff status" -msgstr "" +msgstr "कर्मचारी स्थिती" msgid "Designates whether the user can log into this admin site." -msgstr "" +msgstr "वापरकर्ता या प्रशासक स्थळावर प्रवेश करू शकतो की नाही हे नियुक्त करते." msgid "active" -msgstr "" +msgstr "सक्रिय" msgid "" "Designates whether this user should be treated as active. Unselect this " "instead of deleting accounts." msgstr "" +"या वापरकर्त्याला सक्रिय मानले जावे की नाही हे नियुक्त करते. खाती हटवण्याऐवजी ही निवड " +"कमी करा. " msgid "date joined" -msgstr "" +msgstr "सहभाग दिनांक" msgid "user" -msgstr "" +msgstr "वापरकर्ता" msgid "users" -msgstr "" +msgstr "वापरकर्ते" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "गुप्तशब्द %(verbose_name)s सारखा अत्यंत सामान्य आहे." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "तुमचा गुप्तशब्द तुमच्या इतर वैयक्तिक माहितीशी सारखा असू शकत नाही." + +msgid "This password is too common." +msgstr "हा गुप्तशब्द खूपच सामान्य आहे." + +msgid "Your password can’t be a commonly used password." +msgstr "तुमचा गुप्तशब्द हा सामान्यतः वापरला जाणारा गुप्तशब्द असू शकत नाही." + +msgid "This password is entirely numeric." +msgstr "हा गुप्तशब्द पूर्णपणे संख्यात्मक आहे." + +msgid "Your password can’t be entirely numeric." +msgstr "तुमचा गुप्तशब्द पूर्णपणे संख्यात्मक असू शकत नाही." #, python-format msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s वरील गुप्तशब्द पुनरस्थापना" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." msgstr "" +"वैध वापरकर्तानाव प्रविष्ट करा. या मूल्यामध्ये केवळ असुरक्षित लोअरकेस a-z आणि अपरकेस A-Z " +"अक्षरे, संख्या आणि @/./+/-/_ वर्ण असू शकतात." -msgid "Logged out" +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." msgstr "" +"वैध वापरकर्तानाव प्रविष्ट करा. या मूल्यामध्ये फक्त अक्षरे, संख्या आणि @/./+/-/_ वर्ण असू " +"शकतात." + +msgid "Logged out" +msgstr "बाहेर पडलात" msgid "Password reset" -msgstr "" +msgstr "गुप्तशब्द पुनरस्थापना" msgid "Password reset sent" -msgstr "" +msgstr "गुप्तशब्द पुनरस्थापना पाठविले गेले आहे" msgid "Enter new password" -msgstr "" +msgstr "नवीन गुप्तशब्द लिहा" msgid "Password reset unsuccessful" -msgstr "" +msgstr "गुप्तशब्द पुनरस्थापना अयशस्वी" msgid "Password reset complete" -msgstr "" +msgstr "गुप्तशब्द पुनरस्थापना पूर्ण" msgid "Password change" -msgstr "" +msgstr "गुप्तशब्द बदलणे" msgid "Password change successful" -msgstr "" +msgstr "गुप्तशब्द बदलणे यशस्वी झाले" diff --git a/django/contrib/auth/management/__init__.py b/django/contrib/auth/management/__init__.py index ad31a6e68fa..b29a980cb2d 100644 --- a/django/contrib/auth/management/__init__.py +++ b/django/contrib/auth/management/__init__.py @@ -1,6 +1,7 @@ """ Creates permissions for all installed apps that need permissions. """ + import getpass import unicodedata diff --git a/django/contrib/auth/management/commands/createsuperuser.py b/django/contrib/auth/management/commands/createsuperuser.py index 6d650cca67e..75ef68ff681 100644 --- a/django/contrib/auth/management/commands/createsuperuser.py +++ b/django/contrib/auth/management/commands/createsuperuser.py @@ -1,6 +1,7 @@ """ Management utility to create superusers. """ + import getpass import os import sys @@ -271,15 +272,19 @@ def _get_input_message(self, field, default=None): return "%s%s%s: " % ( capfirst(field.verbose_name), " (leave blank to use '%s')" % default if default else "", - " (%s.%s)" - % ( - field.remote_field.model._meta.object_name, - field.m2m_target_field_name() - if field.many_to_many - else field.remote_field.field_name, - ) - if field.remote_field - else "", + ( + " (%s.%s)" + % ( + field.remote_field.model._meta.object_name, + ( + field.m2m_target_field_name() + if field.many_to_many + else field.remote_field.field_name + ), + ) + if field.remote_field + else "" + ), ) @cached_property diff --git a/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo b/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo index 183b3d14e9f..4f5b10dc657 100644 Binary files a/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po b/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po index 822bd2e63c1..880ce36a51d 100644 --- a/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2014-10-05 20:12+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2024-01-24 19:22+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,25 +18,25 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Content Types" -msgstr "" +msgstr "सामुग्रीचे प्रकार" msgid "python model class name" -msgstr "" +msgstr "पायथन मॉडेल वर्गाचे नाव" msgid "content type" -msgstr "" +msgstr "सामुग्री प्रकार" msgid "content types" -msgstr "" +msgstr "सामुग्रीचे प्रकार" #, python-format msgid "Content type %(ct_id)s object has no associated model" -msgstr "" +msgstr "%(ct_id)s या सामुग्री प्रकाराच्या ऑब्जेक्टला संबंधित मॉडेल नाही." #, python-format -msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" msgstr "" #, python-format -msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" msgstr "" diff --git a/django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo b/django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo index aef2cabae3d..d9b1b120e3b 100644 Binary files a/django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo and b/django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo differ diff --git a/django/contrib/flatpages/locale/af/LC_MESSAGES/django.po b/django/contrib/flatpages/locale/af/LC_MESSAGES/django.po index dbad3064089..dc81ad496c2 100644 --- a/django/contrib/flatpages/locale/af/LC_MESSAGES/django.po +++ b/django/contrib/flatpages/locale/af/LC_MESSAGES/django.po @@ -29,7 +29,7 @@ msgstr "URL" msgid "" "Example: “/about/contact/”. Make sure to have leading and trailing slashes." msgstr "" -"Voorbeeld “/about/kontak/”. Maak seker dat dit begin en eindig met ’n " +"Voorbeeld: “/about/kontak/”. Maak seker dat dit begin en eindig met ’n " "skuinsstreep." msgid "" @@ -41,7 +41,7 @@ msgstr "" msgid "Example: “/about/contact”. Make sure to have a leading slash." msgstr "" -"Voorbeeld “/about/kontak/”. Maak seker dat dit begin met ’n skuinsstreep." +"Voorbeeld: “/about/kontak/”. Maak seker dat dit begin met ’n skuinsstreep." msgid "URL is missing a leading slash." msgstr "’n Skuinsstreep ontbreek vooraan URL." @@ -69,7 +69,7 @@ msgid "" "Example: “flatpages/contact_page.html”. If this isn’t provided, the system " "will use “flatpages/default.html”." msgstr "" -"Voorbeeld “/flatpages/kontakbladsy.html”. As dit weggelaat word, sal die " +"Voorbeeld: “/flatpages/kontakbladsy.html”. As dit weggelaat word, sal die " "stelsel “flatpages/default.html” gebruik." msgid "registration required" diff --git a/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo b/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo index 7d4393d635e..6197eac0e75 100644 Binary files a/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po b/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po index f2bed7f33ac..1d88dc9acb4 100644 --- a/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-03-18 09:16+0100\n" -"PO-Revision-Date: 2015-03-18 08:34+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2024-01-24 19:03+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,56 +18,63 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Advanced options" -msgstr "" +msgstr "प्रगत पर्याय" msgid "Flat Pages" msgstr "" msgid "URL" -msgstr "" +msgstr "यूआरएल" msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "अग्रगण्य आणि अनुगामी स्लॅश असल्याची खात्री करा. उदाहरण: “/about/contact/”." msgid "" "This value must contain only letters, numbers, dots, underscores, dashes, " "slashes or tildes." msgstr "" +"या मूल्यामध्ये फक्त अक्षरे, संख्या, ठिपके, अंडरस्कोअर, डॅश, स्लॅश किंवा टिल्ड असणे आवश्यक आहे." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "अग्रगण्य स्लॅश असल्याची खात्री करा. उदाहरण: “/about/contact”. " msgid "URL is missing a leading slash." -msgstr "" +msgstr "URL मधे अग्रगण्य स्लॅश गहाळ आहे." msgid "URL is missing a trailing slash." -msgstr "" +msgstr "URL मधे अनुगामी स्लॅश गहाळ आहे. " #, python-format msgid "Flatpage with url %(url)s already exists for site %(site)s" msgstr "" msgid "title" -msgstr "" +msgstr "शीर्षक" msgid "content" -msgstr "" +msgstr "सामुग्री" msgid "enable comments" -msgstr "" +msgstr "प्रतिक्रिया सक्षम करा" msgid "template name" -msgstr "" +msgstr "टेम्पलेटचे नाव" msgid "" -"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " -"will use 'flatpages/default.html'." +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." msgstr "" msgid "registration required" -msgstr "" +msgstr "नोंदणी आवश्यक" msgid "If this is checked, only logged-in users will be able to view the page." msgstr "" +msgid "sites" +msgstr "स्थळे" + msgid "flat page" msgstr "" diff --git a/django/contrib/gis/db/backends/oracle/models.py b/django/contrib/gis/db/backends/oracle/models.py index f06f73148e9..af749c3435c 100644 --- a/django/contrib/gis/db/backends/oracle/models.py +++ b/django/contrib/gis/db/backends/oracle/models.py @@ -7,6 +7,7 @@ For example, the `USER_SDO_GEOM_METADATA` is used for the GeometryColumns model and the `SDO_COORD_REF_SYS` is used for the SpatialRefSys model. """ + from django.contrib.gis.db import models from django.contrib.gis.db.backends.base.models import SpatialRefSysMixin diff --git a/django/contrib/gis/db/backends/oracle/operations.py b/django/contrib/gis/db/backends/oracle/operations.py index ed86985cf8d..eb86dc39dee 100644 --- a/django/contrib/gis/db/backends/oracle/operations.py +++ b/django/contrib/gis/db/backends/oracle/operations.py @@ -7,6 +7,7 @@ support for an internal JVM, and Java libraries are required to use the WKT constructors. """ + import re from django.contrib.gis.db import models diff --git a/django/contrib/gis/db/backends/postgis/adapter.py b/django/contrib/gis/db/backends/postgis/adapter.py index c95f9032538..c9715e17567 100644 --- a/django/contrib/gis/db/backends/postgis/adapter.py +++ b/django/contrib/gis/db/backends/postgis/adapter.py @@ -1,6 +1,7 @@ """ This object provides quoting for GEOS geometries into PostgreSQL/PostGIS. """ + from django.contrib.gis.db.backends.postgis.pgraster import to_pgraster from django.contrib.gis.geos import GEOSGeometry from django.db.backends.postgresql.psycopg_any import sql diff --git a/django/contrib/gis/db/backends/postgis/const.py b/django/contrib/gis/db/backends/postgis/const.py index 2f4393d25e5..8bc16a1abb6 100644 --- a/django/contrib/gis/db/backends/postgis/const.py +++ b/django/contrib/gis/db/backends/postgis/const.py @@ -1,6 +1,7 @@ """ PostGIS to GDAL conversion constant definitions """ + # Lookup to convert pixel type values from GDAL to PostGIS GDAL_TO_POSTGIS = [None, 4, 6, 5, 8, 7, 10, 11, None, None, None, None] diff --git a/django/contrib/gis/db/backends/postgis/models.py b/django/contrib/gis/db/backends/postgis/models.py index b7b568274aa..e35ef75ce98 100644 --- a/django/contrib/gis/db/backends/postgis/models.py +++ b/django/contrib/gis/db/backends/postgis/models.py @@ -1,6 +1,7 @@ """ The GeometryColumns and SpatialRefSys models for the PostGIS backend. """ + from django.contrib.gis.db.backends.base.models import SpatialRefSysMixin from django.db import models diff --git a/django/contrib/gis/db/backends/spatialite/models.py b/django/contrib/gis/db/backends/spatialite/models.py index 7cc98ae1268..0f5f7b55ef0 100644 --- a/django/contrib/gis/db/backends/spatialite/models.py +++ b/django/contrib/gis/db/backends/spatialite/models.py @@ -1,6 +1,7 @@ """ The GeometryColumns and SpatialRefSys models for the SpatiaLite backend. """ + from django.contrib.gis.db.backends.base.models import SpatialRefSysMixin from django.db import models diff --git a/django/contrib/gis/db/backends/spatialite/operations.py b/django/contrib/gis/db/backends/spatialite/operations.py index 0b8b26ab6f8..d39f7a9e0d0 100644 --- a/django/contrib/gis/db/backends/spatialite/operations.py +++ b/django/contrib/gis/db/backends/spatialite/operations.py @@ -2,6 +2,7 @@ SQL functions reference lists: https://www.gaia-gis.it/gaia-sins/spatialite-sql-4.3.0.html """ + from django.contrib.gis.db import models from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations from django.contrib.gis.db.backends.spatialite.adapter import SpatiaLiteAdapter diff --git a/django/contrib/gis/db/models/functions.py b/django/contrib/gis/db/models/functions.py index bd02e3717d8..e0f4a057e50 100644 --- a/django/contrib/gis/db/models/functions.py +++ b/django/contrib/gis/db/models/functions.py @@ -127,9 +127,11 @@ def as_sqlite(self, compiler, connection, **extra_context): copy = self.copy() copy.set_source_expressions( [ - Value(float(expr.value)) - if hasattr(expr, "value") and isinstance(expr.value, Decimal) - else expr + ( + Value(float(expr.value)) + if hasattr(expr, "value") and isinstance(expr.value, Decimal) + else expr + ) for expr in copy.get_source_expressions() ] ) @@ -342,9 +344,9 @@ def as_postgresql(self, compiler, connection, **extra_context): def as_sqlite(self, compiler, connection, **extra_context): if self.geo_field.geodetic(connection): # SpatiaLite returns NULL instead of zero on geodetic coordinates - extra_context[ - "template" - ] = "COALESCE(%(function)s(%(expressions)s, %(spheroid)s), 0)" + extra_context["template"] = ( + "COALESCE(%(function)s(%(expressions)s, %(spheroid)s), 0)" + ) extra_context["spheroid"] = int(bool(self.spheroid)) return super().as_sql(compiler, connection, **extra_context) diff --git a/django/contrib/gis/db/models/proxy.py b/django/contrib/gis/db/models/proxy.py index 4db365dc16c..b415e147fc6 100644 --- a/django/contrib/gis/db/models/proxy.py +++ b/django/contrib/gis/db/models/proxy.py @@ -5,6 +5,7 @@ Thanks to Robert Coup for providing this functionality (see #4322). """ + from django.db.models.query_utils import DeferredAttribute diff --git a/django/contrib/gis/db/models/sql/conversion.py b/django/contrib/gis/db/models/sql/conversion.py index be712319fb2..7802b2dd1ec 100644 --- a/django/contrib/gis/db/models/sql/conversion.py +++ b/django/contrib/gis/db/models/sql/conversion.py @@ -2,6 +2,7 @@ This module holds simple classes to convert geospatial values from the database. """ + from decimal import Decimal from django.contrib.gis.measure import Area, Distance diff --git a/django/contrib/gis/gdal/__init__.py b/django/contrib/gis/gdal/__init__.py index 9ed6e311568..e63808d39d9 100644 --- a/django/contrib/gis/gdal/__init__.py +++ b/django/contrib/gis/gdal/__init__.py @@ -25,6 +25,7 @@ by setting `GDAL_LIBRARY_PATH` in your settings with the path to the GDAL C library on your system. """ + from django.contrib.gis.gdal.datasource import DataSource from django.contrib.gis.gdal.driver import Driver from django.contrib.gis.gdal.envelope import Envelope diff --git a/django/contrib/gis/gdal/datasource.py b/django/contrib/gis/gdal/datasource.py index dfd043ab0c2..c7ff48b8f1b 100644 --- a/django/contrib/gis/gdal/datasource.py +++ b/django/contrib/gis/gdal/datasource.py @@ -33,6 +33,7 @@ # OFTReal returns floats, all else returns string. val = field.value """ + from ctypes import byref from pathlib import Path diff --git a/django/contrib/gis/gdal/envelope.py b/django/contrib/gis/gdal/envelope.py index 4c2c1e4a1ad..05832bd7cc4 100644 --- a/django/contrib/gis/gdal/envelope.py +++ b/django/contrib/gis/gdal/envelope.py @@ -10,6 +10,7 @@ | | Lower left (min_x, min_y) o----------+ """ + from ctypes import Structure, c_double from django.contrib.gis.gdal.error import GDALException diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py index f74dc688b3d..8ea6b5ffc46 100644 --- a/django/contrib/gis/gdal/geometries.py +++ b/django/contrib/gis/gdal/geometries.py @@ -38,6 +38,7 @@ >>> print(gt1 == 3, gt1 == 'Polygon') # Equivalence works w/non-OGRGeomType objects True True """ + import sys from binascii import b2a_hex from ctypes import byref, c_char_p, c_double, c_ubyte, c_void_p, string_at diff --git a/django/contrib/gis/gdal/prototypes/ds.py b/django/contrib/gis/gdal/prototypes/ds.py index bc5250e2db2..b6e9d4a0b81 100644 --- a/django/contrib/gis/gdal/prototypes/ds.py +++ b/django/contrib/gis/gdal/prototypes/ds.py @@ -3,6 +3,7 @@ related data structures. OGR_Dr_*, OGR_DS_*, OGR_L_*, OGR_F_*, OGR_Fld_* routines are relevant here. """ + from ctypes import POINTER, c_char_p, c_double, c_int, c_long, c_void_p from django.contrib.gis.gdal.envelope import OGREnvelope diff --git a/django/contrib/gis/gdal/prototypes/errcheck.py b/django/contrib/gis/gdal/prototypes/errcheck.py index 52bb7cb0830..d37e81cdf66 100644 --- a/django/contrib/gis/gdal/prototypes/errcheck.py +++ b/django/contrib/gis/gdal/prototypes/errcheck.py @@ -2,6 +2,7 @@ This module houses the error-checking routines used by the GDAL ctypes prototypes. """ + from ctypes import c_void_p, string_at from django.contrib.gis.gdal.error import GDALException, SRSException, check_err diff --git a/django/contrib/gis/gdal/prototypes/generation.py b/django/contrib/gis/gdal/prototypes/generation.py index 230e56f6655..4d34a96e70d 100644 --- a/django/contrib/gis/gdal/prototypes/generation.py +++ b/django/contrib/gis/gdal/prototypes/generation.py @@ -2,6 +2,7 @@ This module contains functions that generate ctypes prototypes for the GDAL routines. """ + from ctypes import POINTER, c_bool, c_char_p, c_double, c_int, c_int64, c_void_p from functools import partial diff --git a/django/contrib/gis/gdal/prototypes/raster.py b/django/contrib/gis/gdal/prototypes/raster.py index 59b930cb02d..b7871d19694 100644 --- a/django/contrib/gis/gdal/prototypes/raster.py +++ b/django/contrib/gis/gdal/prototypes/raster.py @@ -2,6 +2,7 @@ This module houses the ctypes function prototypes for GDAL DataSource (raster) related data structures. """ + from ctypes import POINTER, c_bool, c_char_p, c_double, c_int, c_void_p from functools import partial diff --git a/django/contrib/gis/gdal/raster/const.py b/django/contrib/gis/gdal/raster/const.py index dccc9cfab4b..a1ab62f37aa 100644 --- a/django/contrib/gis/gdal/raster/const.py +++ b/django/contrib/gis/gdal/raster/const.py @@ -1,6 +1,7 @@ """ GDAL - Constant definitions """ + from ctypes import ( c_double, c_float, diff --git a/django/contrib/gis/gdal/srs.py b/django/contrib/gis/gdal/srs.py index cd0554eb120..85f9c0a9a4a 100644 --- a/django/contrib/gis/gdal/srs.py +++ b/django/contrib/gis/gdal/srs.py @@ -26,6 +26,7 @@ >>> print(srs.name) NAD83 / Texas South Central """ + from ctypes import byref, c_char_p, c_int from enum import IntEnum from types import NoneType diff --git a/django/contrib/gis/geoip2/__init__.py b/django/contrib/gis/geoip2/__init__.py index 71b71f68dba..0df5827c256 100644 --- a/django/contrib/gis/geoip2/__init__.py +++ b/django/contrib/gis/geoip2/__init__.py @@ -11,6 +11,7 @@ Grab GeoLite2-Country.mmdb.gz and GeoLite2-City.mmdb.gz, and unzip them in the directory corresponding to settings.GEOIP_PATH. """ + __all__ = ["HAS_GEOIP2"] try: diff --git a/django/contrib/gis/geos/__init__.py b/django/contrib/gis/geos/__init__.py index 27de1ca8e69..f50cd198565 100644 --- a/django/contrib/gis/geos/__init__.py +++ b/django/contrib/gis/geos/__init__.py @@ -2,6 +2,7 @@ The GeoDjango GEOS module. Please consult the GeoDjango documentation for more details: https://docs.djangoproject.com/en/dev/ref/contrib/gis/geos/ """ + from .collections import ( # NOQA GeometryCollection, MultiLineString, diff --git a/django/contrib/gis/geos/collections.py b/django/contrib/gis/geos/collections.py index abfec8af3d7..35262a56221 100644 --- a/django/contrib/gis/geos/collections.py +++ b/django/contrib/gis/geos/collections.py @@ -2,6 +2,7 @@ This module houses the Geometry Collection objects: GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon """ + from django.contrib.gis.geos import prototypes as capi from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin from django.contrib.gis.geos.libgeos import GEOM_PTR diff --git a/django/contrib/gis/geos/coordseq.py b/django/contrib/gis/geos/coordseq.py index 0ff4ecb2e54..15400e08fe4 100644 --- a/django/contrib/gis/geos/coordseq.py +++ b/django/contrib/gis/geos/coordseq.py @@ -3,6 +3,7 @@ by GEOSGeometry to house the actual coordinates of the Point, LineString, and LinearRing geometries. """ + from ctypes import byref, c_byte, c_double, c_uint from django.contrib.gis.geos import prototypes as capi diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py index 00b36af0a69..8bbe2c264ad 100644 --- a/django/contrib/gis/geos/geometry.py +++ b/django/contrib/gis/geos/geometry.py @@ -2,6 +2,7 @@ This module contains the 'base' GEOSGeometry object -- all GEOS Geometries inherit from this object. """ + import re from ctypes import addressof, byref, c_double diff --git a/django/contrib/gis/geos/io.py b/django/contrib/gis/geos/io.py index d7898065f08..8dd3f289e65 100644 --- a/django/contrib/gis/geos/io.py +++ b/django/contrib/gis/geos/io.py @@ -3,6 +3,7 @@ objects. Specifically, this has Python implementations of WKB/WKT reader and writer classes. """ + from django.contrib.gis.geos.geometry import GEOSGeometry from django.contrib.gis.geos.prototypes.io import ( WKBWriter, diff --git a/django/contrib/gis/geos/libgeos.py b/django/contrib/gis/geos/libgeos.py index 1121b4f7154..b883c6c0902 100644 --- a/django/contrib/gis/geos/libgeos.py +++ b/django/contrib/gis/geos/libgeos.py @@ -6,6 +6,7 @@ This module also houses GEOS Pointer utilities, including get_pointer_arr(), and GEOM_PTR. """ + import logging import os from ctypes import CDLL, CFUNCTYPE, POINTER, Structure, c_char_p diff --git a/django/contrib/gis/geos/prototypes/errcheck.py b/django/contrib/gis/geos/prototypes/errcheck.py index a527f513a7a..42b24c28913 100644 --- a/django/contrib/gis/geos/prototypes/errcheck.py +++ b/django/contrib/gis/geos/prototypes/errcheck.py @@ -1,6 +1,7 @@ """ Error checking functions for GEOS ctypes prototype functions. """ + from ctypes import c_void_p, string_at from django.contrib.gis.geos.error import GEOSException diff --git a/django/contrib/gis/geos/prototypes/misc.py b/django/contrib/gis/geos/prototypes/misc.py index fccd0ecc9e4..bd5859e79bb 100644 --- a/django/contrib/gis/geos/prototypes/misc.py +++ b/django/contrib/gis/geos/prototypes/misc.py @@ -2,6 +2,7 @@ This module is for the miscellaneous GEOS routines, particularly the ones that return the area, distance, and length. """ + from ctypes import POINTER, c_double, c_int from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory diff --git a/django/contrib/gis/geos/prototypes/predicates.py b/django/contrib/gis/geos/prototypes/predicates.py index 32b790173a6..dd07cbfb269 100644 --- a/django/contrib/gis/geos/prototypes/predicates.py +++ b/django/contrib/gis/geos/prototypes/predicates.py @@ -2,6 +2,7 @@ This module houses the GEOS ctypes prototype functions for the unary and binary predicate operations on geometries. """ + from ctypes import c_byte, c_char_p, c_double from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory diff --git a/django/contrib/gis/geos/prototypes/topology.py b/django/contrib/gis/geos/prototypes/topology.py index e61eae964a9..9323bb2d160 100644 --- a/django/contrib/gis/geos/prototypes/topology.py +++ b/django/contrib/gis/geos/prototypes/topology.py @@ -2,6 +2,7 @@ This module houses the GEOS ctypes prototype functions for the topological operations on geometries. """ + from ctypes import c_double, c_int from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory diff --git a/django/contrib/gis/locale/mn/LC_MESSAGES/django.mo b/django/contrib/gis/locale/mn/LC_MESSAGES/django.mo index 2ebb08f69c0..8643c1fe724 100644 Binary files a/django/contrib/gis/locale/mn/LC_MESSAGES/django.mo and b/django/contrib/gis/locale/mn/LC_MESSAGES/django.mo differ diff --git a/django/contrib/gis/locale/mn/LC_MESSAGES/django.po b/django/contrib/gis/locale/mn/LC_MESSAGES/django.po index 83403a48fd1..1362f6c9e3e 100644 --- a/django/contrib/gis/locale/mn/LC_MESSAGES/django.po +++ b/django/contrib/gis/locale/mn/LC_MESSAGES/django.po @@ -4,6 +4,7 @@ # Baskhuu Lodoikhuu , 2011 # Jannis Leidel , 2011 # Mariusz Felisiak , 2023 +# Turmunkh Batkhuyag, 2023 # Zorig, 2014,2016 # Анхбаяр Анхаа , 2011-2012,2015 # Баясгалан Цэвлээ , 2011,2015 @@ -12,8 +13,8 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 18:45+0000\n" -"Last-Translator: Mariusz Felisiak , 2023\n" +"PO-Revision-Date: 2023-12-24 18:45+0000\n" +"Last-Translator: Turmunkh Batkhuyag, 2023\n" "Language-Team: Mongolian (http://app.transifex.com/django/django/language/" "mn/)\n" "MIME-Version: 1.0\n" @@ -53,7 +54,7 @@ msgid "Multi polygon" msgstr "Олон өнцөгтийн олонлог" msgid "Geometry collection" -msgstr "Дүрсний цуглуулга" +msgstr "Геометрийн цуглуулга" msgid "Extent Aggregate Field" msgstr "Aggregate талбарыг өргөтгөх" @@ -62,20 +63,19 @@ msgid "Raster Field" msgstr "Растер талбар" msgid "No geometry value provided." -msgstr "Дүрс оруулаагүй байна." +msgstr "Геометрийн утгыг өгөөгүй." msgid "Invalid geometry value." -msgstr "Буруу дүрс байна." +msgstr "Буруу геометрийн утга байна." msgid "Invalid geometry type." -msgstr "Дүрсийн төрөл буруу байна." +msgstr "Геометер төрөл буруу байна." msgid "" "An error occurred when transforming the geometry to the SRID of the geometry " "form field." msgstr "" -"An error occurred when transforming the geometry to the SRID дүрсний форм " -"талбарын SRID утгыг хөрвүүлэхэд алдаа гарлаа." +"Геометрийг геометрийн форм талбарын SRID болгон хувиргах үед алдаа гарлаа." msgid "Delete all Features" msgstr "Бүх онцлогүүдыг устгах" diff --git a/django/contrib/gis/locale/mr/LC_MESSAGES/django.mo b/django/contrib/gis/locale/mr/LC_MESSAGES/django.mo index 0fc4a9cedae..2c755725db9 100644 Binary files a/django/contrib/gis/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/gis/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/gis/locale/mr/LC_MESSAGES/django.po b/django/contrib/gis/locale/mr/LC_MESSAGES/django.po index 83ef357230e..1083d9520eb 100644 --- a/django/contrib/gis/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/gis/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-03-18 09:16+0100\n" -"PO-Revision-Date: 2015-03-18 08:35+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-01-24 18:45+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,7 +20,11 @@ msgstr "" msgid "GIS" msgstr "" -msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." msgstr "" msgid "Point" @@ -46,6 +51,9 @@ msgstr "" msgid "Extent Aggregate Field" msgstr "" +msgid "Raster Field" +msgstr "" + msgid "No geometry value provided." msgstr "" @@ -61,13 +69,7 @@ msgid "" msgstr "" msgid "Delete all Features" -msgstr "" - -msgid "WKT debugging window:" -msgstr "" - -msgid "Google Maps via GeoDjango" -msgstr "" +msgstr "सर्व वैशिष्ट्ये घालवा" msgid "Debugging window (serialized value)" msgstr "" @@ -76,5 +78,5 @@ msgid "No feeds are registered." msgstr "" #, python-format -msgid "Slug %r isn't registered." +msgid "Slug %r isn’t registered." msgstr "" diff --git a/django/contrib/gis/utils/__init__.py b/django/contrib/gis/utils/__init__.py index 12f032c6658..f42fa90226e 100644 --- a/django/contrib/gis/utils/__init__.py +++ b/django/contrib/gis/utils/__init__.py @@ -1,6 +1,7 @@ """ This module contains useful utilities for GeoDjango. """ + from django.contrib.gis.utils.ogrinfo import ogrinfo from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect from django.contrib.gis.utils.srs import add_srs_entry diff --git a/django/contrib/gis/utils/ogrinspect.py b/django/contrib/gis/utils/ogrinspect.py index 40ca0cb4615..76c8bfbcfab 100644 --- a/django/contrib/gis/utils/ogrinspect.py +++ b/django/contrib/gis/utils/ogrinspect.py @@ -3,6 +3,7 @@ models for GeoDjango and/or mapping dictionaries for use with the `LayerMapping` utility. """ + from django.contrib.gis.gdal import DataSource from django.contrib.gis.gdal.field import ( OFTDate, diff --git a/django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo b/django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo index de62154a085..0f2c700ef91 100644 Binary files a/django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo and b/django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo differ diff --git a/django/contrib/humanize/locale/mn/LC_MESSAGES/django.po b/django/contrib/humanize/locale/mn/LC_MESSAGES/django.po index 8b2de470c0f..94bb307b786 100644 --- a/django/contrib/humanize/locale/mn/LC_MESSAGES/django.po +++ b/django/contrib/humanize/locale/mn/LC_MESSAGES/django.po @@ -3,6 +3,7 @@ # Translators: # Bayarkhuu Bataa, 2014 # Bayarkhuu Bataa, 2013 +# Turmunkh Batkhuyag, 2023 # Zorig, 2013 # Zorig, 2019 # Анхбаяр Анхаа , 2013 @@ -10,10 +11,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-01-16 20:42+0100\n" -"PO-Revision-Date: 2019-02-19 02:28+0000\n" -"Last-Translator: Zorig\n" -"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-24 18:40+0000\n" +"Last-Translator: Turmunkh Batkhuyag, 2023\n" +"Language-Team: Mongolian (http://app.transifex.com/django/django/language/" "mn/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -27,24 +28,24 @@ msgstr "Хүнчлэх" #. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). msgctxt "ordinal 11, 12, 13" msgid "{}th" -msgstr "{} дэхь" +msgstr "{} дэх" #. Translators: Ordinal format when value ends with 0, e.g. 80th. msgctxt "ordinal 0" msgid "{}th" -msgstr "{} дэхь" +msgstr "{} дэх" #. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. msgctxt "ordinal 1" msgid "{}st" -msgstr "{} дэхь" +msgstr "{} дэх" #. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. msgctxt "ordinal 2" msgid "{}nd" msgstr "{} дахь" -#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. msgctxt "ordinal 3" msgid "{}rd" msgstr "{} дахь" @@ -52,38 +53,32 @@ msgstr "{} дахь" #. Translators: Ordinal format when value ends with 4, e.g. 84th. msgctxt "ordinal 4" msgid "{}th" -msgstr "{} дахь" +msgstr "{} дэх" #. Translators: Ordinal format when value ends with 5, e.g. 85th. msgctxt "ordinal 5" msgid "{}th" -msgstr "{} дэхь" +msgstr "{} дахь" #. Translators: Ordinal format when value ends with 6, e.g. 86th. msgctxt "ordinal 6" msgid "{}th" -msgstr "{} дэхь" +msgstr "{} дахь" #. Translators: Ordinal format when value ends with 7, e.g. 87th. msgctxt "ordinal 7" msgid "{}th" -msgstr "{} дэхь" +msgstr "{} дахь" #. Translators: Ordinal format when value ends with 8, e.g. 88th. msgctxt "ordinal 8" msgid "{}th" -msgstr "{} дэхь" +msgstr "{} дахь" #. Translators: Ordinal format when value ends with 9, e.g. 89th. msgctxt "ordinal 9" msgid "{}th" -msgstr "{} дэхь" - -#, python-format -msgid "%(value).1f million" -msgid_plural "%(value).1f million" -msgstr[0] "%(value).1f сая" -msgstr[1] "%(value).1f сая" +msgstr "{} дэх" #, python-format msgid "%(value)s million" @@ -91,35 +86,17 @@ msgid_plural "%(value)s million" msgstr[0] "%(value)s сая" msgstr[1] "%(value)s сая" -#, python-format -msgid "%(value).1f billion" -msgid_plural "%(value).1f billion" -msgstr[0] "%(value).1f тэрбум" -msgstr[1] "%(value).1f тэрбум" - #, python-format msgid "%(value)s billion" msgid_plural "%(value)s billion" msgstr[0] "%(value)s тэрбум" msgstr[1] "%(value)s тэрбум" -#, python-format -msgid "%(value).1f trillion" -msgid_plural "%(value).1f trillion" -msgstr[0] "%(value).1f наяд" -msgstr[1] "%(value).1f наяд" - #, python-format msgid "%(value)s trillion" msgid_plural "%(value)s trillion" msgstr[0] "%(value)s наяд" -msgstr[1] "%(value)s наяд" - -#, python-format -msgid "%(value).1f quadrillion" -msgid_plural "%(value).1f quadrillion" -msgstr[0] "%(value).1f тунамал" -msgstr[1] "%(value).1f тунамал" +msgstr[1] "%(value)s их наяд" #, python-format msgid "%(value)s quadrillion" @@ -127,84 +104,42 @@ msgid_plural "%(value)s quadrillion" msgstr[0] "%(value)s тунамал" msgstr[1] "%(value)s тунамал" -#, python-format -msgid "%(value).1f quintillion" -msgid_plural "%(value).1f quintillion" -msgstr[0] "%(value).1f их ингүүмэл " -msgstr[1] "%(value).1f их ингүүмэл " - #, python-format msgid "%(value)s quintillion" msgid_plural "%(value)s quintillion" msgstr[0] "%(value)s их ингүүмэл " msgstr[1] "%(value)s их ингүүмэл " -#, python-format -msgid "%(value).1f sextillion" -msgid_plural "%(value).1f sextillion" -msgstr[0] "%(value).1f ялгаруулагч" -msgstr[1] "%(value).1f ялгаруулагч" - #, python-format msgid "%(value)s sextillion" msgid_plural "%(value)s sextillion" msgstr[0] "%(value)s ялгаруулагч" msgstr[1] "%(value)s ялгаруулагч" -#, python-format -msgid "%(value).1f septillion" -msgid_plural "%(value).1f septillion" -msgstr[0] "%(value).1f их өөр дээр " -msgstr[1] "%(value).1f их өөр дээр " - #, python-format msgid "%(value)s septillion" msgid_plural "%(value)s septillion" msgstr[0] "%(value)s их өөр дээр " msgstr[1] "%(value)s их өөр дээр " -#, python-format -msgid "%(value).1f octillion" -msgid_plural "%(value).1f octillion" -msgstr[0] "%(value).1f өөр дээр " -msgstr[1] "%(value).1f өөр дээр " - #, python-format msgid "%(value)s octillion" msgid_plural "%(value)s octillion" msgstr[0] "%(value)s өөр дээр " msgstr[1] "%(value)s өөр дээр " -#, python-format -msgid "%(value).1f nonillion" -msgid_plural "%(value).1f nonillion" -msgstr[0] "%(value).1f их шалтгааны үзэгдэл" -msgstr[1] "%(value).1f их шалтгааны үзэгдэл" - #, python-format msgid "%(value)s nonillion" msgid_plural "%(value)s nonillion" msgstr[0] "%(value)s их шалтгааны үзэгдэл" msgstr[1] "%(value)s их шалтгааны үзэгдэл" -#, python-format -msgid "%(value).1f decillion" -msgid_plural "%(value).1f decillion" -msgstr[0] "%(value).1f эрхэт" -msgstr[1] "%(value).1f эрхэт" - #, python-format msgid "%(value)s decillion" msgid_plural "%(value)s decillion" msgstr[0] "%(value)s эрхэт" msgstr[1] "%(value)s эрхэт" -#, python-format -msgid "%(value).1f googol" -msgid_plural "%(value).1f googol" -msgstr[0] "%(value).1f googol" -msgstr[1] "%(value).1f googol" - #, python-format msgid "%(value)s googol" msgid_plural "%(value)s googol" @@ -313,86 +248,86 @@ msgstr "одооноос %(delta)s " #. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' #, python-format msgctxt "naturaltime-past" -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "%d жил" -msgstr[1] "%d жилүүд" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d жил" +msgstr[1] "%(num)d жил" #, python-format msgctxt "naturaltime-past" -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "%d сар" -msgstr[1] "%d сар" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d сар" +msgstr[1] "%(num)d сар" #, python-format msgctxt "naturaltime-past" -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "%d долоо хоног" -msgstr[1] "%d долоо хоног" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d долоо хоног" +msgstr[1] "%(num)d долоо хоног" #, python-format msgctxt "naturaltime-past" -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "%d өдөр" -msgstr[1] "%d өдөр" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d өдөр" +msgstr[1] "%(num)d өдөр" #, python-format msgctxt "naturaltime-past" -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "%d цаг" -msgstr[1] "%d цаг" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d цаг" +msgstr[1] "%(num)d цаг" #, python-format msgctxt "naturaltime-past" -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "%d минут" -msgstr[1] "%d минут" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минут" +msgstr[1] "%(num)d минут" #. Translators: 'naturaltime-future' strings will be included in '%(delta)s #. from now' #, python-format msgctxt "naturaltime-future" -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "%d жил" -msgstr[1] "%d жил" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d жил" +msgstr[1] "%(num)d жил" #, python-format msgctxt "naturaltime-future" -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "%d сар" -msgstr[1] "%d сар" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d сар" +msgstr[1] "%(num)d сар" #, python-format msgctxt "naturaltime-future" -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "%d долоо хоног" -msgstr[1] "%d долоо хоног" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d долоо хоног" +msgstr[1] "%(num)d долоо хоног" #, python-format msgctxt "naturaltime-future" -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "%d өдөр" -msgstr[1] "%d өдөр" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d өдөр" +msgstr[1] "%(num)d өдөр" #, python-format msgctxt "naturaltime-future" -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "%d цаг" -msgstr[1] "%d цаг" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d цаг" +msgstr[1] "%(num)d цаг" #, python-format msgctxt "naturaltime-future" -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "%d минут" -msgstr[1] "%d минут" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минут" +msgstr[1] "%(num)d минут" diff --git a/django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo b/django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo index 183b3d14e9f..9e758b08fc3 100644 Binary files a/django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/humanize/locale/mr/LC_MESSAGES/django.po b/django/contrib/humanize/locale/mr/LC_MESSAGES/django.po index b042b29121a..97d741ba36d 100644 --- a/django/contrib/humanize/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/humanize/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2014-10-05 20:12+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-01-24 18:40+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,25 +18,62 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Humanize" -msgstr "" - -msgid "th" -msgstr "" - -msgid "st" -msgstr "" - -msgid "nd" -msgstr "" - -msgid "rd" -msgstr "" - -#, python-format -msgid "%(value).1f million" -msgid_plural "%(value).1f million" -msgstr[0] "" -msgstr[1] "" +msgstr "मानवीकरण" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}वा" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{वा}" #, python-format msgid "%(value)s million" @@ -43,120 +81,60 @@ msgid_plural "%(value)s million" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f billion" -msgid_plural "%(value).1f billion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s billion" msgid_plural "%(value)s billion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f trillion" -msgid_plural "%(value).1f trillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s trillion" msgid_plural "%(value)s trillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f quadrillion" -msgid_plural "%(value).1f quadrillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s quadrillion" msgid_plural "%(value)s quadrillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f quintillion" -msgid_plural "%(value).1f quintillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s quintillion" msgid_plural "%(value)s quintillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f sextillion" -msgid_plural "%(value).1f sextillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s sextillion" msgid_plural "%(value)s sextillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f septillion" -msgid_plural "%(value).1f septillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s septillion" msgid_plural "%(value)s septillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f octillion" -msgid_plural "%(value).1f octillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s octillion" msgid_plural "%(value)s octillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f nonillion" -msgid_plural "%(value).1f nonillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s nonillion" msgid_plural "%(value)s nonillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f decillion" -msgid_plural "%(value).1f decillion" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s decillion" msgid_plural "%(value)s decillion" msgstr[0] "" msgstr[1] "" -#, python-format -msgid "%(value).1f googol" -msgid_plural "%(value).1f googol" -msgstr[0] "" -msgstr[1] "" - #, python-format msgid "%(value)s googol" msgid_plural "%(value)s googol" @@ -164,98 +142,187 @@ msgstr[0] "" msgstr[1] "" msgid "one" -msgstr "" +msgstr "एक" msgid "two" -msgstr "" +msgstr "दोन" msgid "three" -msgstr "" +msgstr "तीन" msgid "four" -msgstr "" +msgstr "चार" msgid "five" -msgstr "" +msgstr "पाच" msgid "six" -msgstr "" +msgstr "सहा" msgid "seven" -msgstr "" +msgstr "सात" msgid "eight" -msgstr "" +msgstr "आठ" msgid "nine" -msgstr "" +msgstr "नऊ" msgid "today" -msgstr "" +msgstr "आज" msgid "tomorrow" -msgstr "" +msgstr "उद्या" msgid "yesterday" -msgstr "" +msgstr "काल" +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' #, python-format -msgctxt "naturaltime" msgid "%(delta)s ago" -msgstr "" +msgstr "%(delta)s पूर्वी" -msgid "now" -msgstr "" - -#. Translators: please keep a non-breaking space (U+00A0) -#. between count and time unit. +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. #, python-format -msgid "a second ago" -msgid_plural "%(count)s seconds ago" +msgid "an hour ago" +msgid_plural "%(count)s hours ago" msgstr[0] "" msgstr[1] "" -#. Translators: please keep a non-breaking space (U+00A0) -#. between count and time unit. +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. #, python-format msgid "a minute ago" msgid_plural "%(count)s minutes ago" msgstr[0] "" msgstr[1] "" -#. Translators: please keep a non-breaking space (U+00A0) -#. between count and time unit. +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. #, python-format -msgid "an hour ago" -msgid_plural "%(count)s hours ago" +msgid "a second ago" +msgid_plural "%(count)s seconds ago" msgstr[0] "" msgstr[1] "" -#, python-format -msgctxt "naturaltime" -msgid "%(delta)s from now" -msgstr "" +msgid "now" +msgstr "आता" -#. Translators: please keep a non-breaking space (U+00A0) -#. between count and time unit. +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. #, python-format msgid "a second from now" msgid_plural "%(count)s seconds from now" msgstr[0] "" msgstr[1] "" -#. Translators: please keep a non-breaking space (U+00A0) -#. between count and time unit. +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. #, python-format msgid "a minute from now" msgid_plural "%(count)s minutes from now" msgstr[0] "" msgstr[1] "" -#. Translators: please keep a non-breaking space (U+00A0) -#. between count and time unit. +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. #, python-format msgid "an hour from now" msgid_plural "%(count)s hours from now" msgstr[0] "" msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/django/contrib/humanize/templatetags/humanize.py b/django/contrib/humanize/templatetags/humanize.py index 23224779c55..2c26f8944a7 100644 --- a/django/contrib/humanize/templatetags/humanize.py +++ b/django/contrib/humanize/templatetags/humanize.py @@ -75,12 +75,13 @@ def intcomma(value, use_l10n=True): return intcomma(value, False) else: return number_format(value, use_l10n=True, force_grouping=True) - orig = str(value) - new = re.sub(r"^(-?\d+)(\d{3})", r"\g<1>,\g<2>", orig) - if orig == new: - return new - else: - return intcomma(new, use_l10n) + result = str(value) + match = re.match(r"-?\d+", result) + if match: + prefix = match[0] + prefix_with_commas = re.sub(r"\d{3}", r"\g<0>,", prefix[::-1])[::-1] + result = prefix_with_commas + result[len(prefix) :] + return result # A tuple of standard large number to their converters diff --git a/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo b/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo index 652b8fd85f9..e5b798fb05c 100644 Binary files a/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo and b/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po b/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po index 4c93f29da63..35664e99edd 100644 --- a/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po +++ b/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po @@ -1,15 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Swara , 2022 +# Swara , 2022,2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-01-17 02:13-0600\n" -"PO-Revision-Date: 2023-04-19 09:22+0000\n" -"Last-Translator: Swara , 2022\n" -"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"PO-Revision-Date: 2024-01-19 09:22+0000\n" +"Last-Translator: Swara , 2022,2024\n" +"Language-Team: Central Kurdish (http://app.transifex.com/django/django/" "language/ckb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -93,9 +93,9 @@ msgstr "هەندێک کلیلی نەناسراو دابین کران: %(keys)s" #, python-format msgid "" "Ensure that the upper bound of the range is not greater than %(limit_value)s." -msgstr "" +msgstr "دڵنیابە لەوەی کە سنووری سەرەوەی ڕێژەکە زیاتر نییە لە %(limit_value)s." #, python-format msgid "" "Ensure that the lower bound of the range is not less than %(limit_value)s." -msgstr "" +msgstr "دڵنیابە لەوەی کە سنووری خوارەوەی ڕێژەکە کەمتر نییە لە %(limit_value)s." diff --git a/django/contrib/postgres/locale/mr/LC_MESSAGES/django.mo b/django/contrib/postgres/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 00000000000..d183857384a Binary files /dev/null and b/django/contrib/postgres/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/postgres/locale/mr/LC_MESSAGES/django.po b/django/contrib/postgres/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 00000000000..42fb58dec0c --- /dev/null +++ b/django/contrib/postgres/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,97 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Omkar Parab, 2024 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2024-01-19 09:22+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "" + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "JSON डेटा लोड करू शकलो नाही. " + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "दोन वैध मूल्ये प्रविष्ट करा." + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "दोन पूर्ण संख्या प्रविष्ट करा." + +msgid "Enter two numbers." +msgstr "दोन संख्या प्रविष्ट करा." + +msgid "Enter two valid date/times." +msgstr "दोन वैध दिनांक/वेळा प्रविष्ट करा." + +msgid "Enter two valid dates." +msgstr "दोन वैध दिनांका प्रविष्ट करा" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" diff --git a/django/contrib/postgres/search.py b/django/contrib/postgres/search.py index 936709c2f84..4d279857c66 100644 --- a/django/contrib/postgres/search.py +++ b/django/contrib/postgres/search.py @@ -116,9 +116,11 @@ def as_sql(self, compiler, connection, function=None, template=None): clone.set_source_expressions( [ Coalesce( - expression - if isinstance(expression.output_field, (CharField, TextField)) - else Cast(expression, TextField()), + ( + expression + if isinstance(expression.output_field, (CharField, TextField)) + else Cast(expression, TextField()) + ), Value(""), ) for expression in clone.get_source_expressions() diff --git a/django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo b/django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo index 183b3d14e9f..54b53f3bea3 100644 Binary files a/django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/redirects/locale/mr/LC_MESSAGES/django.po b/django/contrib/redirects/locale/mr/LC_MESSAGES/django.po index 5477dd9c9e6..403f9fabe8c 100644 --- a/django/contrib/redirects/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/redirects/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2014-10-05 20:12+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2024-01-24 18:32+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,26 +18,31 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Redirects" -msgstr "" +msgstr "पुनर्निर्देशने" + +msgid "site" +msgstr "स्थळ" msgid "redirect from" -msgstr "" +msgstr "पासून पुनर्निर्देशित" msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "डोमेन नाव वगळून हा एक परिपूर्ण मार्ग असावा. उदाहरण: \"/events/search/\"." msgid "redirect to" -msgstr "" +msgstr "ला पुनर्निर्देशित" msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." msgstr "" +"हा एकतर निरपेक्ष मार्ग असू शकतो (वरीलप्रमाणे) किंवा एखाद्या योजनेपासून सुरू होणारी पूर्ण " +"URL असू शकते जसे की \"https://\"" msgid "redirect" -msgstr "" +msgstr "पुनर्निर्देशित" msgid "redirects" -msgstr "" +msgstr "पुनर्निर्देशने" diff --git a/django/contrib/sessions/base_session.py b/django/contrib/sessions/base_session.py index 603d2fe12cd..8809dd36f77 100644 --- a/django/contrib/sessions/base_session.py +++ b/django/contrib/sessions/base_session.py @@ -2,6 +2,7 @@ This module allows importing AbstractBaseSession even when django.contrib.sessions is not in INSTALLED_APPS. """ + from django.db import models from django.utils.translation import gettext_lazy as _ diff --git a/django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo b/django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo index 183b3d14e9f..0dc523de98e 100644 Binary files a/django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/sessions/locale/mr/LC_MESSAGES/django.po b/django/contrib/sessions/locale/mr/LC_MESSAGES/django.po index 45b727e128e..cefc17d3008 100644 --- a/django/contrib/sessions/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/sessions/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2014-10-05 20:12+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"PO-Revision-Date: 2024-01-24 18:26+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,19 +18,19 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Sessions" -msgstr "" +msgstr "सत्रे" msgid "session key" -msgstr "" +msgstr "सत्राची किल्ली" msgid "session data" -msgstr "" +msgstr "सत्रातील डेटा" msgid "expire date" -msgstr "" +msgstr "संपण्याची दिनांक" msgid "session" -msgstr "" +msgstr "सत्र" msgid "sessions" -msgstr "" +msgstr "सत्रे" diff --git a/django/contrib/sites/locale/mr/LC_MESSAGES/django.mo b/django/contrib/sites/locale/mr/LC_MESSAGES/django.mo index 183b3d14e9f..40f14123d20 100644 Binary files a/django/contrib/sites/locale/mr/LC_MESSAGES/django.mo and b/django/contrib/sites/locale/mr/LC_MESSAGES/django.mo differ diff --git a/django/contrib/sites/locale/mr/LC_MESSAGES/django.po b/django/contrib/sites/locale/mr/LC_MESSAGES/django.po index fc1e2a9358f..3e041c141ed 100644 --- a/django/contrib/sites/locale/mr/LC_MESSAGES/django.po +++ b/django/contrib/sites/locale/mr/LC_MESSAGES/django.po @@ -1,14 +1,15 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Omkar Parab, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2014-10-05 20:12+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"PO-Revision-Date: 2024-01-24 18:05+0000\n" +"Last-Translator: Omkar Parab, 2024\n" +"Language-Team: Marathi (http://app.transifex.com/django/django/language/" "mr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,19 +18,19 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Sites" -msgstr "" +msgstr "स्थळे" msgid "The domain name cannot contain any spaces or tabs." -msgstr "" +msgstr "डोमेन नावामध्ये कोणताही स्पेस किंवा टॅब असू शकत नाहीत." msgid "domain name" -msgstr "" +msgstr "डोमेनचे नाव" msgid "display name" -msgstr "" +msgstr "प्रदर्शन नाव" msgid "site" -msgstr "" +msgstr "स्थळ" msgid "sites" -msgstr "" +msgstr "स्थळे" diff --git a/django/contrib/staticfiles/views.py b/django/contrib/staticfiles/views.py index 83d04d4cec1..3fb2677322d 100644 --- a/django/contrib/staticfiles/views.py +++ b/django/contrib/staticfiles/views.py @@ -3,6 +3,7 @@ development, and SHOULD NOT be used in a production setting. """ + import os import posixpath diff --git a/django/core/cache/__init__.py b/django/core/cache/__init__.py index eb7fa5b2e99..444d958e688 100644 --- a/django/core/cache/__init__.py +++ b/django/core/cache/__init__.py @@ -12,6 +12,7 @@ See docs/topics/cache.txt for information on the public API. """ + from django.core import signals from django.core.cache.backends.base import ( BaseCache, diff --git a/django/core/exceptions.py b/django/core/exceptions.py index 2a2288ff4dc..31c18ee7e16 100644 --- a/django/core/exceptions.py +++ b/django/core/exceptions.py @@ -1,6 +1,7 @@ """ Global Django exception and warning classes. """ + import operator from django.utils.hashable import make_hashable diff --git a/django/core/files/images.py b/django/core/files/images.py index 6a603f24fca..7c1532ac8fd 100644 --- a/django/core/files/images.py +++ b/django/core/files/images.py @@ -3,6 +3,7 @@ Requires Pillow as you might imagine. """ + import struct import zlib diff --git a/django/core/files/locks.py b/django/core/files/locks.py index c0f471f87da..a7a7a22dce4 100644 --- a/django/core/files/locks.py +++ b/django/core/files/locks.py @@ -16,6 +16,7 @@ ... locks.lock(f, locks.LOCK_EX) ... f.write('Django') """ + import os __all__ = ("LOCK_EX", "LOCK_SH", "LOCK_NB", "lock", "unlock") diff --git a/django/core/files/uploadhandler.py b/django/core/files/uploadhandler.py index b6c185e8fc7..ab86f7fede5 100644 --- a/django/core/files/uploadhandler.py +++ b/django/core/files/uploadhandler.py @@ -1,6 +1,7 @@ """ Base file upload handler classes, and the built-in concrete subclasses """ + import os from io import BytesIO diff --git a/django/core/handlers/asgi.py b/django/core/handlers/asgi.py index 7b0086fb765..3af080599ab 100644 --- a/django/core/handlers/asgi.py +++ b/django/core/handlers/asgi.py @@ -186,11 +186,18 @@ async def handle(self, scope, receive, send): if request is None: body_file.close() await self.send_response(error_response, send) + await sync_to_async(error_response.close)() return async def process_request(request, send): response = await self.run_get_response(request) - await self.send_response(response, send) + try: + await self.send_response(response, send) + except asyncio.CancelledError: + # Client disconnected during send_response (ignore exception). + pass + + return response # Try to catch a disconnect while getting response. tasks = [ @@ -221,6 +228,14 @@ async def process_request(request, send): except asyncio.CancelledError: # Task re-raised the CancelledError as expected. pass + + try: + response = tasks[1].result() + except asyncio.CancelledError: + await signals.request_finished.asend(sender=self.__class__) + else: + await sync_to_async(response.close)() + body_file.close() async def listen_for_disconnect(self, receive): @@ -346,7 +361,6 @@ async def send_response(self, response, send): "more_body": not last, } ) - await sync_to_async(response.close, thread_sensitive=True)() @classmethod def chunk_bytes(cls, data): diff --git a/django/core/mail/__init__.py b/django/core/mail/__init__.py index dc63e8702c6..676326697b2 100644 --- a/django/core/mail/__init__.py +++ b/django/core/mail/__init__.py @@ -1,6 +1,7 @@ """ Tools for sending email. """ + from django.conf import settings # Imported for backwards compatibility and for the sake diff --git a/django/core/mail/backends/console.py b/django/core/mail/backends/console.py index ee5dd285043..2d7c778cc15 100644 --- a/django/core/mail/backends/console.py +++ b/django/core/mail/backends/console.py @@ -1,6 +1,7 @@ """ Email backend that writes messages to console instead of sending them. """ + import sys import threading diff --git a/django/core/mail/backends/smtp.py b/django/core/mail/backends/smtp.py index 1ee48269aee..6820148ac12 100644 --- a/django/core/mail/backends/smtp.py +++ b/django/core/mail/backends/smtp.py @@ -1,4 +1,5 @@ """SMTP email backend class.""" + import smtplib import ssl import threading diff --git a/django/core/management/base.py b/django/core/management/base.py index 631c761c004..4c47e1c6e51 100644 --- a/django/core/management/base.py +++ b/django/core/management/base.py @@ -2,6 +2,7 @@ Base classes for writing management commands (named commands which can be executed through ``django-admin`` or ``manage.py``). """ + import argparse import os import sys @@ -528,9 +529,11 @@ def check( if issues: visible_issue_count += len(issues) formatted = ( - self.style.ERROR(str(e)) - if e.is_serious() - else self.style.WARNING(str(e)) + ( + self.style.ERROR(str(e)) + if e.is_serious() + else self.style.WARNING(str(e)) + ) for e in issues ) formatted = "\n".join(sorted(formatted)) @@ -543,11 +546,15 @@ def check( if visible_issue_count: footer += "\n" footer += "System check identified %s (%s silenced)." % ( - "no issues" - if visible_issue_count == 0 - else "1 issue" - if visible_issue_count == 1 - else "%s issues" % visible_issue_count, + ( + "no issues" + if visible_issue_count == 0 + else ( + "1 issue" + if visible_issue_count == 1 + else "%s issues" % visible_issue_count + ) + ), len(all_issues) - visible_issue_count, ) diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index cc183517e30..01ff8974dd1 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -219,7 +219,10 @@ def get_objects(count_only=False): if count_only: yield queryset.order_by().count() else: - yield from queryset.iterator() + chunk_size = ( + 2000 if queryset._prefetch_related_lookups else None + ) + yield from queryset.iterator(chunk_size=chunk_size) try: self.stdout.ending = None diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py index 20dffac05f7..1fbca9244b0 100644 --- a/django/core/serializers/base.py +++ b/django/core/serializers/base.py @@ -1,6 +1,7 @@ """ Module for abstract serializer/unserializer base classes. """ + from io import StringIO from django.core.exceptions import ObjectDoesNotExist diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index 3f9955aa23c..16b69770f6c 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -1,6 +1,7 @@ """ XML serializer. """ + import json from xml.dom import pulldom from xml.sax import handler diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index 1062e9fecaa..d2c8c659797 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -412,10 +412,13 @@ def db_default_sql(self, field): """Return the sql and params for the field's database default.""" from django.db.models.expressions import Value - sql = "%s" if isinstance(field.db_default, Value) else "(%s)" + db_default = field._db_default_expression + sql = ( + self._column_default_sql(field) if isinstance(db_default, Value) else "(%s)" + ) query = Query(model=field.model) compiler = query.get_compiler(connection=self.connection) - default_sql, params = compiler.compile(field.db_default) + default_sql, params = compiler.compile(db_default) if self.connection.features.requires_literal_defaults: # Some databases doesn't support parameterized defaults (Oracle, # SQLite). If this is the case, the individual schema backend @@ -725,9 +728,9 @@ def add_field(self, model, field): namespace, _ = split_identifier(model._meta.db_table) definition += " " + self.sql_create_column_inline_fk % { "name": self._fk_constraint_name(model, field, constraint_suffix), - "namespace": "%s." % self.quote_name(namespace) - if namespace - else "", + "namespace": ( + "%s." % self.quote_name(namespace) if namespace else "" + ), "column": self.quote_name(field.column), "to_table": self.quote_name(to_table), "to_column": self.quote_name(to_column), @@ -1642,6 +1645,14 @@ def _field_should_be_altered(self, old_field, new_field, ignore=None): ): old_kwargs.pop("to", None) new_kwargs.pop("to", None) + # db_default can take many form but result in the same SQL. + if ( + old_kwargs.get("db_default") + and new_kwargs.get("db_default") + and self.db_default_sql(old_field) == self.db_default_sql(new_field) + ): + old_kwargs.pop("db_default") + new_kwargs.pop("db_default") return self.quote_name(old_field.column) != self.quote_name( new_field.column ) or (old_path, old_args, old_kwargs) != (new_path, new_args, new_kwargs) @@ -1925,11 +1936,13 @@ def _constraint_names( """Return all constraint names matching the columns and conditions.""" if column_names is not None: column_names = [ - self.connection.introspection.identifier_converter( - truncate_name(name, self.connection.ops.max_name_length()) + ( + self.connection.introspection.identifier_converter( + truncate_name(name, self.connection.ops.max_name_length()) + ) + if self.connection.features.truncates_names + else self.connection.introspection.identifier_converter(name) ) - if self.connection.features.truncates_names - else self.connection.introspection.identifier_converter(name) for name in column_names ] with self.connection.cursor() as cursor: diff --git a/django/db/backends/ddl_references.py b/django/db/backends/ddl_references.py index 412d07a993d..75787ef8ab5 100644 --- a/django/db/backends/ddl_references.py +++ b/django/db/backends/ddl_references.py @@ -2,6 +2,7 @@ Helpers to manipulate deferred DDL statements that might need to be adjusted or discarded within when executing a migration. """ + from copy import deepcopy diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index e2707a9bfdb..3349497e867 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -3,6 +3,7 @@ Requires mysqlclient: https://pypi.org/project/mysqlclient/ """ + from django.core.exceptions import ImproperlyConfigured from django.db import IntegrityError from django.db.backends import utils as backend_utils diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py index 803c3a5baf0..6347d8e3984 100644 --- a/django/db/backends/oracle/base.py +++ b/django/db/backends/oracle/base.py @@ -3,6 +3,7 @@ Requires oracledb: https://oracle.github.io/python-oracledb/ """ + import datetime import decimal import os @@ -300,7 +301,7 @@ def init_connection_state(self): @async_unsafe def create_cursor(self, name=None): - return FormatStylePlaceholderCursor(self.connection) + return FormatStylePlaceholderCursor(self.connection, self) def _commit(self): if self.connection is not None: @@ -365,11 +366,15 @@ def __init__(self, param, cursor, strings_only=False): param = Oracle_datetime.from_datetime(param) string_size = 0 - # Oracle doesn't recognize True and False correctly. - if param is True: - param = 1 - elif param is False: - param = 0 + has_boolean_data_type = ( + cursor.database.features.supports_boolean_expr_in_select_clause + ) + if not has_boolean_data_type: + # Oracle < 23c doesn't recognize True and False correctly. + if param is True: + param = 1 + elif param is False: + param = 0 if hasattr(param, "bind_parameter"): self.force_bytes = param.bind_parameter(cursor) elif isinstance(param, (Database.Binary, datetime.timedelta)): @@ -389,6 +394,8 @@ def __init__(self, param, cursor, strings_only=False): self.input_size = Database.CLOB elif isinstance(param, datetime.datetime): self.input_size = Database.TIMESTAMP + elif has_boolean_data_type and isinstance(param, bool): + self.input_size = Database.DB_TYPE_BOOLEAN else: self.input_size = None @@ -426,9 +433,10 @@ class FormatStylePlaceholderCursor: charset = "utf-8" - def __init__(self, connection): + def __init__(self, connection, database): self.cursor = connection.cursor() self.cursor.outputtypehandler = self._output_type_handler + self.database = database @staticmethod def _output_number_converter(value): @@ -446,7 +454,7 @@ def _get_decimal_converter(precision, scale): def _output_type_handler(cursor, name, defaultType, length, precision, scale): """ Called for each db column fetched from cursors. Return numbers as the - appropriate Python type. + appropriate Python type, and NCLOB with JSON as strings. """ if defaultType == Database.NUMBER: if scale == -127: @@ -476,6 +484,10 @@ def _output_type_handler(cursor, name, defaultType, length, precision, scale): arraysize=cursor.arraysize, outconverter=outconverter, ) + # oracledb 2.0.0+ returns NLOB columns with IS JSON constraints as + # dicts. Use a no-op converter to avoid this. + elif defaultType == Database.DB_TYPE_NCLOB: + return cursor.var(Database.DB_TYPE_NCLOB, arraysize=cursor.arraysize) def _format_params(self, params): try: @@ -528,14 +540,24 @@ def _fix_for_params(self, query, params, unify_by_values=False): # values. It can be used only in single query execute() because # executemany() shares the formatted query with each of the params # list. e.g. for input params = [0.75, 2, 0.75, 'sth', 0.75] - # params_dict = {0.75: ':arg0', 2: ':arg1', 'sth': ':arg2'} + # params_dict = { + # (float, 0.75): ':arg0', + # (int, 2): ':arg1', + # (str, 'sth'): ':arg2', + # } # args = [':arg0', ':arg1', ':arg0', ':arg2', ':arg0'] # params = {':arg0': 0.75, ':arg1': 2, ':arg2': 'sth'} + # The type of parameters in param_types keys is necessary to avoid + # unifying 0/1 with False/True. + param_types = [(type(param), param) for param in params] params_dict = { - param: ":arg%d" % i for i, param in enumerate(dict.fromkeys(params)) + param_type: ":arg%d" % i + for i, param_type in enumerate(dict.fromkeys(param_types)) + } + args = [params_dict[param_type] for param_type in param_types] + params = { + placeholder: param for (_, param), placeholder in params_dict.items() } - args = [params_dict[param] for param in params] - params = {value: key for key, value in params_dict.items()} query %= tuple(args) else: # Handle params as sequence diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py index df773bff8c2..b0a51777286 100644 --- a/django/db/backends/oracle/creation.py +++ b/django/db/backends/oracle/creation.py @@ -133,20 +133,20 @@ def _switch_to_test_user(self, parameters): credentials in the SAVED_USER/SAVED_PASSWORD key in the settings dict. """ real_settings = settings.DATABASES[self.connection.alias] - real_settings["SAVED_USER"] = self.connection.settings_dict[ - "SAVED_USER" - ] = self.connection.settings_dict["USER"] + real_settings["SAVED_USER"] = self.connection.settings_dict["SAVED_USER"] = ( + self.connection.settings_dict["USER"] + ) real_settings["SAVED_PASSWORD"] = self.connection.settings_dict[ "SAVED_PASSWORD" ] = self.connection.settings_dict["PASSWORD"] real_test_settings = real_settings["TEST"] test_settings = self.connection.settings_dict["TEST"] - real_test_settings["USER"] = real_settings["USER"] = test_settings[ - "USER" - ] = self.connection.settings_dict["USER"] = parameters["user"] - real_settings["PASSWORD"] = self.connection.settings_dict[ - "PASSWORD" - ] = parameters["password"] + real_test_settings["USER"] = real_settings["USER"] = test_settings["USER"] = ( + self.connection.settings_dict["USER"] + ) = parameters["user"] + real_settings["PASSWORD"] = self.connection.settings_dict["PASSWORD"] = ( + parameters["password"] + ) def set_as_test_mirror(self, primary_settings_dict): """ diff --git a/django/db/backends/oracle/features.py b/django/db/backends/oracle/features.py index 8a02e098d68..ee1cfaa0d99 100644 --- a/django/db/backends/oracle/features.py +++ b/django/db/backends/oracle/features.py @@ -76,7 +76,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_slicing_ordering_in_compound = True requires_compound_order_by_subquery = True allows_multiple_constraints_on_same_fields = False - supports_boolean_expr_in_select_clause = False supports_comparing_boolean_expr = False supports_json_field_contains = False supports_collation_on_textfield = False @@ -119,6 +118,9 @@ class DatabaseFeatures(BaseDatabaseFeatures): "Oracle doesn't support comparing NCLOB to NUMBER.": { "generic_relations_regress.tests.GenericRelationTests.test_textlink_filter", }, + "Oracle doesn't support casting filters to NUMBER.": { + "lookup.tests.LookupQueryingTests.test_aggregate_combined_lookup", + }, } django_test_expected_failures = { # A bug in Django/oracledb with respect to string handling (#23843). @@ -166,3 +168,7 @@ def supports_collation_on_charfield(self): @cached_property def supports_primitives_in_json_field(self): return self.connection.oracle_version >= (21,) + + @cached_property + def supports_boolean_expr_in_select_clause(self): + return self.connection.oracle_version >= (23,) diff --git a/django/db/backends/oracle/utils.py b/django/db/backends/oracle/utils.py index 930b8e09186..28be58c73db 100644 --- a/django/db/backends/oracle/utils.py +++ b/django/db/backends/oracle/utils.py @@ -21,6 +21,7 @@ class InsertVar: "PositiveBigIntegerField": int, "PositiveSmallIntegerField": int, "PositiveIntegerField": int, + "BooleanField": int, "FloatField": Database.NATIVE_FLOAT, "DateTimeField": Database.TIMESTAMP, "DateField": Database.Date, diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py index d92ad587102..c950a9a616b 100644 --- a/django/db/backends/postgresql/base.py +++ b/django/db/backends/postgresql/base.py @@ -226,9 +226,11 @@ def get_connection_params(self): server_side_binding = conn_params.pop("server_side_binding", None) conn_params.setdefault( "cursor_factory", - ServerBindingCursor - if is_psycopg3 and server_side_binding is True - else Cursor, + ( + ServerBindingCursor + if is_psycopg3 and server_side_binding is True + else Cursor + ), ) if settings_dict["USER"]: conn_params["user"] = settings_dict["USER"] diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py index 5dc93a27d05..842830be304 100644 --- a/django/db/backends/postgresql/schema.py +++ b/django/db/backends/postgresql/schema.py @@ -267,9 +267,9 @@ def _alter_column_collation_sql( % { "column": self.quote_name(new_field.column), "type": new_type, - "collation": " " + self._collate_sql(new_collation) - if new_collation - else "", + "collation": ( + " " + self._collate_sql(new_collation) if new_collation else "" + ), }, [], ) diff --git a/django/db/backends/sqlite3/_functions.py b/django/db/backends/sqlite3/_functions.py index 7e86950f7df..0171b60f387 100644 --- a/django/db/backends/sqlite3/_functions.py +++ b/django/db/backends/sqlite3/_functions.py @@ -1,6 +1,7 @@ """ Implementations of SQL functions for SQLite. """ + import functools import random import statistics diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index 08de0bad5aa..10a296c992c 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -1,6 +1,7 @@ """ SQLite backend for the sqlite3 module in the standard library. """ + import datetime import decimal import warnings diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py index 3a0ee511ff4..13af3f0c039 100644 --- a/django/db/migrations/autodetector.py +++ b/django/db/migrations/autodetector.py @@ -566,11 +566,12 @@ def generate_renamed_models(self): rem_model_state.app_label, rem_model_state.name_lower, ) - self.renamed_models_rel[ - renamed_models_rel_key - ] = "%s.%s" % ( - model_state.app_label, - model_state.name_lower, + self.renamed_models_rel[renamed_models_rel_key] = ( + "%s.%s" + % ( + model_state.app_label, + model_state.name_lower, + ) ) self.old_model_keys.remove((rem_app_label, rem_model_name)) self.old_model_keys.add((app_label, model_name)) @@ -971,9 +972,9 @@ def create_renamed_fields(self): (rem_app_label, rem_model_name, rem_field_name) ) old_field_keys.add((app_label, model_name, field_name)) - self.renamed_fields[ - app_label, model_name, field_name - ] = rem_field_name + self.renamed_fields[app_label, model_name, field_name] = ( + rem_field_name + ) break def generate_renamed_fields(self): diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py index 81dcd06e04d..50445f31014 100644 --- a/django/db/migrations/loader.py +++ b/django/db/migrations/loader.py @@ -131,11 +131,11 @@ def load_disk(self): "Migration %s in app %s has no Migration class" % (migration_name, app_config.label) ) - self.disk_migrations[ - app_config.label, migration_name - ] = migration_module.Migration( - migration_name, - app_config.label, + self.disk_migrations[app_config.label, migration_name] = ( + migration_module.Migration( + migration_name, + app_config.label, + ) ) def get_migration(self, app_label, name_prefix): diff --git a/django/db/migrations/operations/models.py b/django/db/migrations/operations/models.py index b18ef553695..98d563d26a6 100644 --- a/django/db/migrations/operations/models.py +++ b/django/db/migrations/operations/models.py @@ -55,11 +55,11 @@ def __init__(self, name, fields, options=None, bases=None, managers=None): _check_for_duplicates( "bases", ( - base._meta.label_lower - if hasattr(base, "_meta") - else base.lower() - if isinstance(base, str) - else base + ( + base._meta.label_lower + if hasattr(base, "_meta") + else base.lower() if isinstance(base, str) else base + ) for base in self.bases ), ) diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py index ae55967383f..bb2a19edbb5 100644 --- a/django/db/migrations/state.py +++ b/django/db/migrations/state.py @@ -525,11 +525,11 @@ def _get_concrete_models_mapping_and_proxy_models(self): if model_state.options.get("proxy"): proxy_models[model_key] = model_state # Find a concrete model for the proxy. - concrete_models_mapping[ - model_key - ] = self._find_concrete_model_from_proxy( - proxy_models, - model_state, + concrete_models_mapping[model_key] = ( + self._find_concrete_model_from_proxy( + proxy_models, + model_state, + ) ) else: concrete_models_mapping[model_key] = model_key diff --git a/django/db/models/aggregates.py b/django/db/models/aggregates.py index a778cd413b3..0cbffacd1b9 100644 --- a/django/db/models/aggregates.py +++ b/django/db/models/aggregates.py @@ -1,6 +1,7 @@ """ Classes to represent the definitions of aggregate functions. """ + from django.core.exceptions import FieldError, FullResultSet from django.db.models.expressions import Case, Func, Star, Value, When from django.db.models.fields import IntegerField diff --git a/django/db/models/base.py b/django/db/models/base.py index 80503d118af..3b949c80bf0 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -781,7 +781,11 @@ def save( if force_insert and (force_update or update_fields): raise ValueError("Cannot force both insert and updating in model saving.") - deferred_fields = self.get_deferred_fields() + deferred_non_generated_fields = { + f.attname + for f in self._meta.concrete_fields + if f.attname not in self.__dict__ and f.generated is False + } if update_fields is not None: # If update_fields is empty, skip the save. We do also check for # no-op saves later on for inheritance cases. This bailout is @@ -802,12 +806,16 @@ def save( # If saving to the same database, and this model is deferred, then # automatically do an "update_fields" save on the loaded fields. - elif not force_insert and deferred_fields and using == self._state.db: + elif ( + not force_insert + and deferred_non_generated_fields + and using == self._state.db + ): field_names = set() for field in self._meta.concrete_fields: if not field.primary_key and not hasattr(field, "through"): field_names.add(field.attname) - loaded_fields = field_names.difference(deferred_fields) + loaded_fields = field_names.difference(deferred_non_generated_fields) if loaded_fields: update_fields = frozenset(loaded_fields) @@ -1553,7 +1561,7 @@ def clean_fields(self, exclude=None): errors = {} for f in self._meta.fields: - if f.name in exclude: + if f.name in exclude or f.generated: continue # Skip validation for empty fields with blank=True. The developer # is responsible for making sure they have a valid value. @@ -2221,9 +2229,11 @@ def _check_ordering(cls): opts = cls._meta valid_fields = set( chain.from_iterable( - (f.name, f.attname) - if not (f.auto_created and not f.concrete) - else (f.field.related_query_name(),) + ( + (f.name, f.attname) + if not (f.auto_created and not f.concrete) + else (f.field.related_query_name(),) + ) for f in chain(opts.fields, opts.related_objects) ) ) diff --git a/django/db/models/constants.py b/django/db/models/constants.py index a0c99c95fc7..cec1b9b90f7 100644 --- a/django/db/models/constants.py +++ b/django/db/models/constants.py @@ -1,6 +1,7 @@ """ Constants used across the ORM in general. """ + from enum import Enum # Separator used to split filter strings apart. diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index b162da513d9..4c1f570766f 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -203,9 +203,11 @@ def set_source_expressions(self, exprs): def _parse_expressions(self, *expressions): return [ - arg - if hasattr(arg, "resolve_expression") - else (F(arg) if isinstance(arg, str) else Value(arg)) + ( + arg + if hasattr(arg, "resolve_expression") + else (F(arg) if isinstance(arg, str) else Value(arg)) + ) for arg in expressions ] @@ -284,9 +286,11 @@ def resolve_expression( c.is_summary = summarize c.set_source_expressions( [ - expr.resolve_expression(query, allow_joins, reuse, summarize) - if expr - else None + ( + expr.resolve_expression(query, allow_joins, reuse, summarize) + if expr + else None + ) for expr in c.get_source_expressions() ] ) @@ -365,22 +369,16 @@ def convert_value(self): field = self.output_field internal_type = field.get_internal_type() if internal_type == "FloatField": - return ( - lambda value, expression, connection: None - if value is None - else float(value) + return lambda value, expression, connection: ( + None if value is None else float(value) ) elif internal_type.endswith("IntegerField"): - return ( - lambda value, expression, connection: None - if value is None - else int(value) + return lambda value, expression, connection: ( + None if value is None else int(value) ) elif internal_type == "DecimalField": - return ( - lambda value, expression, connection: None - if value is None - else Decimal(value) + return lambda value, expression, connection: ( + None if value is None else Decimal(value) ) return self._convert_value_noop @@ -426,9 +424,11 @@ def prefix_references(self, prefix): clone = self.copy() clone.set_source_expressions( [ - F(f"{prefix}{expr.name}") - if isinstance(expr, F) - else expr.prefix_references(prefix) + ( + F(f"{prefix}{expr.name}") + if isinstance(expr, F) + else expr.prefix_references(prefix) + ) for expr in self.get_source_expressions() ] ) @@ -1702,10 +1702,13 @@ def as_sql(self, compiler, connection, template=None, **extra_context): return (template % placeholders).rstrip(), params def as_oracle(self, compiler, connection): - # Oracle doesn't allow ORDER BY EXISTS() or filters unless it's wrapped - # in a CASE WHEN. - if connection.ops.conditional_expression_supported_in_where_clause( - self.expression + # Oracle < 23c doesn't allow ORDER BY EXISTS() or filters unless it's + # wrapped in a CASE WHEN. + if ( + not connection.features.supports_boolean_expr_in_select_clause + and connection.ops.conditional_expression_supported_in_where_clause( + self.expression + ) ): copy = self.copy() copy.expression = Case( diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index ce3bebb5917..26cb1bc485e 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -218,12 +218,6 @@ def __init__( self.remote_field = rel self.is_relation = self.remote_field is not None self.default = default - if db_default is not NOT_PROVIDED and not hasattr( - db_default, "resolve_expression" - ): - from django.db.models.expressions import Value - - db_default = Value(db_default) self.db_default = db_default self.editable = editable self.serialize = serialize @@ -407,7 +401,7 @@ def _check_db_default(self, databases=None, **kwargs): continue connection = connections[db] - if not getattr(self.db_default, "allowed_default", False) and ( + if not getattr(self._db_default_expression, "allowed_default", False) and ( connection.features.supports_expression_defaults ): msg = f"{self.db_default} cannot be used in db_default." @@ -993,7 +987,7 @@ def pre_save(self, model_instance, add): from django.db.models.expressions import DatabaseDefault if isinstance(value, DatabaseDefault): - return self.db_default + return self._db_default_expression return value def get_prep_value(self, value): @@ -1046,6 +1040,17 @@ def _get_default(self): return return_None return str # return empty string + @cached_property + def _db_default_expression(self): + db_default = self.db_default + if db_default is not NOT_PROVIDED and not hasattr( + db_default, "resolve_expression" + ): + from django.db.models.expressions import Value + + db_default = Value(db_default, self) + return db_default + def get_choices( self, include_blank=True, diff --git a/django/db/models/fields/generated.py b/django/db/models/fields/generated.py index 95d19582de1..257feeeba26 100644 --- a/django/db/models/fields/generated.py +++ b/django/db/models/fields/generated.py @@ -58,7 +58,13 @@ def generated_sql(self, connection): resolved_expression = self.expression.resolve_expression( self._query, allow_joins=False ) - return compiler.compile(resolved_expression) + sql, params = compiler.compile(resolved_expression) + if ( + getattr(self.expression, "conditional", False) + and not connection.features.supports_boolean_expr_in_select_clause + ): + sql = f"CASE WHEN {sql} THEN 1 ELSE 0 END" + return sql, params def check(self, **kwargs): databases = kwargs.get("databases") or [] diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index 46a5823647d..81cb35b35a3 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -62,6 +62,7 @@ class Child(Model): If you're looking for ``ForwardManyToManyDescriptor`` or ``ReverseManyToManyDescriptor``, use ``ManyToManyDescriptor`` instead. """ + import warnings from asgiref.sync import sync_to_async diff --git a/django/db/models/fields/reverse_related.py b/django/db/models/fields/reverse_related.py index c74e92ba89f..144cce6142c 100644 --- a/django/db/models/fields/reverse_related.py +++ b/django/db/models/fields/reverse_related.py @@ -8,6 +8,7 @@ They also act as reverse fields for the purposes of the Meta API because they're the closest concept currently available. """ + import warnings from django.core import exceptions diff --git a/django/db/models/functions/comparison.py b/django/db/models/functions/comparison.py index eec2ab752d1..b3c02da2426 100644 --- a/django/db/models/functions/comparison.py +++ b/django/db/models/functions/comparison.py @@ -1,4 +1,5 @@ """Database functions that do comparisons or type conversions.""" + from django.db import NotSupportedError from django.db.models.expressions import Func, Value from django.db.models.fields import TextField diff --git a/django/db/models/functions/datetime.py b/django/db/models/functions/datetime.py index fca211e065d..9937e79f6ff 100644 --- a/django/db/models/functions/datetime.py +++ b/django/db/models/functions/datetime.py @@ -318,9 +318,11 @@ def resolve_expression( "Cannot truncate DateField '%s' to %s." % ( field.name, - output_field.__class__.__name__ - if has_explicit_output_field - else "DateTimeField", + ( + output_field.__class__.__name__ + if has_explicit_output_field + else "DateTimeField" + ), ) ) elif isinstance(field, TimeField) and ( @@ -331,9 +333,11 @@ def resolve_expression( "Cannot truncate TimeField '%s' to %s." % ( field.name, - output_field.__class__.__name__ - if has_explicit_output_field - else "DateTimeField", + ( + output_field.__class__.__name__ + if has_explicit_output_field + else "DateTimeField" + ), ) ) return copy diff --git a/django/db/models/functions/math.py b/django/db/models/functions/math.py index 460143ba5af..5fa4654a843 100644 --- a/django/db/models/functions/math.py +++ b/django/db/models/functions/math.py @@ -47,9 +47,11 @@ def as_sqlite(self, compiler, connection, **extra_context): clone = self.copy() clone.set_source_expressions( [ - Cast(expression, FloatField()) - if isinstance(expression.output_field, IntegerField) - else expression + ( + Cast(expression, FloatField()) + if isinstance(expression.output_field, IntegerField) + else expression + ) for expression in self.get_source_expressions()[::-1] ] ) diff --git a/django/db/models/functions/mixins.py b/django/db/models/functions/mixins.py index caf20e131d8..d983df7725a 100644 --- a/django/db/models/functions/mixins.py +++ b/django/db/models/functions/mixins.py @@ -14,9 +14,11 @@ def as_postgresql(self, compiler, connection, **extra_context): clone = self.copy() clone.set_source_expressions( [ - Cast(expression, output_field) - if isinstance(expression.output_field, FloatField) - else expression + ( + Cast(expression, output_field) + if isinstance(expression.output_field, FloatField) + else expression + ) for expression in self.get_source_expressions() ] ) diff --git a/django/db/models/indexes.py b/django/db/models/indexes.py index b5451f9e241..0ddfefec387 100644 --- a/django/db/models/indexes.py +++ b/django/db/models/indexes.py @@ -196,9 +196,11 @@ def __repr__(self): "" if not self.fields else " fields=%s" % repr(self.fields), "" if not self.expressions else " expressions=%s" % repr(self.expressions), "" if not self.name else " name=%s" % repr(self.name), - "" - if self.db_tablespace is None - else " db_tablespace=%s" % repr(self.db_tablespace), + ( + "" + if self.db_tablespace is None + else " db_tablespace=%s" % repr(self.db_tablespace) + ), "" if self.condition is None else " condition=%s" % self.condition, "" if not self.include else " include=%s" % repr(self.include), "" if not self.opclasses else " opclasses=%s" % repr(self.opclasses), diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py index a562a3db386..76c2822caba 100644 --- a/django/db/models/lookups.py +++ b/django/db/models/lookups.py @@ -270,9 +270,11 @@ def get_db_prep_lookup(self, value, connection): ) return ( "%s", - [get_db_prep_value(v, connection, prepared=True) for v in value] - if self.get_db_prep_lookup_value_is_iterable - else [get_db_prep_value(value, connection, prepared=True)], + ( + [get_db_prep_value(v, connection, prepared=True) for v in value] + if self.get_db_prep_lookup_value_is_iterable + else [get_db_prep_value(value, connection, prepared=True)] + ), ) diff --git a/django/db/models/query.py b/django/db/models/query.py index de00bba8d75..153fb1193eb 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -109,9 +109,11 @@ def __iter__(self): related_objs, operator.attrgetter( *[ - field.attname - if from_field == "self" - else queryset.model._meta.get_field(from_field).attname + ( + field.attname + if from_field == "self" + else queryset.model._meta.get_field(from_field).attname + ) for from_field in field.from_fields ] ), @@ -1391,9 +1393,7 @@ def values_list(self, *fields, flat=False, named=False): clone._iterable_class = ( NamedValuesListIterable if named - else FlatValuesListIterable - if flat - else ValuesListIterable + else FlatValuesListIterable if flat else ValuesListIterable ) return clone @@ -1659,9 +1659,11 @@ def _annotate(self, args, kwargs, select=True): if names is None: names = set( chain.from_iterable( - (field.name, field.attname) - if hasattr(field, "attname") - else (field.name,) + ( + (field.name, field.attname) + if hasattr(field, "attname") + else (field.name,) + ) for field in self.model._meta.get_fields() ) ) diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py index 4f3358eb8da..e1041b96537 100644 --- a/django/db/models/query_utils.py +++ b/django/db/models/query_utils.py @@ -5,6 +5,7 @@ large and/or so that they can be used by other modules without getting into circular import difficulties. """ + import functools import inspect import logging diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index b28dc925ba3..421b880deb9 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -1216,9 +1216,9 @@ def get_related_klass_infos(klass_info, related_klass_infos): "field": f, "reverse": False, "local_setter": f.set_cached_value, - "remote_setter": f.remote_field.set_cached_value - if f.unique - else lambda x, y: None, + "remote_setter": ( + f.remote_field.set_cached_value if f.unique else lambda x, y: None + ), "from_parent": False, } related_klass_infos.append(klass_info) @@ -1817,6 +1817,7 @@ def execute_sql(self, returning_fields=None): ) opts = self.query.get_meta() self.returning_fields = returning_fields + cols = [] with self.connection.cursor() as cursor: for sql, params in self.as_sql(): cursor.execute(sql, params) @@ -1827,6 +1828,7 @@ def execute_sql(self, returning_fields=None): and len(self.query.objs) > 1 ): rows = self.connection.ops.fetch_returned_insert_rows(cursor) + cols = [field.get_col(opts.db_table) for field in self.returning_fields] elif self.connection.features.can_return_columns_from_insert: assert len(self.query.objs) == 1 rows = [ @@ -1835,7 +1837,9 @@ def execute_sql(self, returning_fields=None): self.returning_params, ) ] + cols = [field.get_col(opts.db_table) for field in self.returning_fields] else: + cols = [opts.pk.get_col(opts.db_table)] rows = [ ( self.connection.ops.last_insert_id( @@ -1845,7 +1849,6 @@ def execute_sql(self, returning_fields=None): ), ) ] - cols = [field.get_col(opts.db_table) for field in self.returning_fields] converters = self.get_converters(cols) if converters: rows = list(self.apply_converters(rows, converters)) diff --git a/django/db/models/sql/datastructures.py b/django/db/models/sql/datastructures.py index 5eaa8c25f6b..7c0c14a46e8 100644 --- a/django/db/models/sql/datastructures.py +++ b/django/db/models/sql/datastructures.py @@ -2,6 +2,7 @@ Useful auxiliary data structures for query construction. Not useful outside the SQL domain. """ + import warnings from django.core.exceptions import FullResultSet diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index f04b1c4cc3a..277e8a18ca4 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -6,6 +6,7 @@ databases). The abstraction barrier only works one way: this module has to know all about the internals of models in order to get the information it needs. """ + import copy import difflib import functools @@ -90,18 +91,30 @@ def get_children_from_q(q): def get_child_with_renamed_prefix(prefix, replacement, child): + from django.db.models.query import QuerySet + if isinstance(child, Node): return rename_prefix_from_q(prefix, replacement, child) if isinstance(child, tuple): lhs, rhs = child - lhs = lhs.replace(prefix, replacement, 1) + if lhs.startswith(prefix + LOOKUP_SEP): + lhs = lhs.replace(prefix, replacement, 1) if not isinstance(rhs, F) and hasattr(rhs, "resolve_expression"): rhs = get_child_with_renamed_prefix(prefix, replacement, rhs) return lhs, rhs if isinstance(child, F): child = child.copy() - child.name = child.name.replace(prefix, replacement, 1) + if child.name.startswith(prefix + LOOKUP_SEP): + child.name = child.name.replace(prefix, replacement, 1) + elif isinstance(child, QuerySet): + # QuerySet may contain OuterRef() references which cannot work properly + # without repointing to the filtered annotation and will spawn a + # different JOIN. Always raise ValueError instead of providing partial + # support in other cases. + raise ValueError( + "Passing a QuerySet within a FilteredRelation is not supported." + ) elif hasattr(child, "resolve_expression"): child = child.copy() child.set_source_expressions( diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py index 2f23a2932ce..9c5740c2cdd 100644 --- a/django/db/models/sql/where.py +++ b/django/db/models/sql/where.py @@ -1,6 +1,7 @@ """ Code to manage the creation and SQL rendering of 'where' constraints. """ + import operator from functools import reduce diff --git a/django/forms/models.py b/django/forms/models.py index ff4b83fe596..90779e18fb7 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -2,6 +2,7 @@ Helper functions for creating Form classes from Django models and database field objects. """ + from itertools import chain from django.core.exceptions import ( @@ -830,9 +831,12 @@ def validate_unique(self): ) # Reduce Model instances to their primary key values row_data = tuple( - d._get_pk_val() if hasattr(d, "_get_pk_val") - # Prevent "unhashable type: list" errors later on. - else tuple(d) if isinstance(d, list) else d + ( + d._get_pk_val() + if hasattr(d, "_get_pk_val") + # Prevent "unhashable type: list" errors later on. + else tuple(d) if isinstance(d, list) else d + ) for d in row_data ) if row_data and None not in row_data: diff --git a/django/forms/widgets.py b/django/forms/widgets.py index 2c734052d5b..4fae110d5ed 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -101,9 +101,11 @@ def render(self): def render_js(self): return [ - path.__html__() - if hasattr(path, "__html__") - else format_html('', self.absolute_path(path)) + ( + path.__html__() + if hasattr(path, "__html__") + else format_html('', self.absolute_path(path)) + ) for path in self._js ] @@ -113,12 +115,14 @@ def render_css(self): media = sorted(self._css) return chain.from_iterable( [ - path.__html__() - if hasattr(path, "__html__") - else format_html( - '', - self.absolute_path(path), - medium, + ( + path.__html__() + if hasattr(path, "__html__") + else format_html( + '', + self.absolute_path(path), + medium, + ) ) for path in self._css[medium] ] diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py index 5ab63455efc..94e5116639b 100644 --- a/django/http/multipartparser.py +++ b/django/http/multipartparser.py @@ -4,6 +4,7 @@ Exposes one class, ``MultiPartParser``, which feeds chunks of uploaded data to file upload handlers for processing. """ + import base64 import binascii import collections diff --git a/django/http/request.py b/django/http/request.py index fe15a173be5..4c27d576ba4 100644 --- a/django/http/request.py +++ b/django/http/request.py @@ -170,9 +170,11 @@ def _get_full_path(self, path, force_append_slash): return "%s%s%s" % ( escape_uri_path(path), "/" if force_append_slash and not path.endswith("/") else "", - ("?" + iri_to_uri(self.META.get("QUERY_STRING", ""))) - if self.META.get("QUERY_STRING", "") - else "", + ( + ("?" + iri_to_uri(self.META.get("QUERY_STRING", ""))) + if self.META.get("QUERY_STRING", "") + else "" + ), ) def get_signed_cookie(self, key, default=RAISE_ERROR, salt="", max_age=None): diff --git a/django/middleware/csrf.py b/django/middleware/csrf.py index 2c0d2cc1206..f7943494ba2 100644 --- a/django/middleware/csrf.py +++ b/django/middleware/csrf.py @@ -4,6 +4,7 @@ This module provides a middleware that implements protection against request forgeries from other sites. """ + import logging import string from collections import defaultdict diff --git a/django/shortcuts.py b/django/shortcuts.py index 822e6107aca..b8b5be1f5f5 100644 --- a/django/shortcuts.py +++ b/django/shortcuts.py @@ -3,6 +3,7 @@ of MVC. In other words, these functions/classes introduce controlled coupling for convenience's sake. """ + from django.http import ( Http404, HttpResponse, diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py index 589ca384142..1f1ea4d7a9e 100644 --- a/django/template/defaultfilters.py +++ b/django/template/defaultfilters.py @@ -1,4 +1,5 @@ """Default variable filters.""" + import random as random_module import re import types diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 79c10232bbc..deb6b01fb6f 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -1,4 +1,5 @@ """Default tags used by the template system, available to all templates.""" + import re import sys import warnings diff --git a/django/template/engine.py b/django/template/engine.py index f2215c0e4e9..9882d3a16d1 100644 --- a/django/template/engine.py +++ b/django/template/engine.py @@ -70,9 +70,11 @@ def __repr__(self): self.__class__.__qualname__, "" if not self.dirs else " dirs=%s" % repr(self.dirs), self.app_dirs, - "" - if not self.context_processors - else " context_processors=%s" % repr(self.context_processors), + ( + "" + if not self.context_processors + else " context_processors=%s" % repr(self.context_processors) + ), self.debug, repr(self.loaders), repr(self.string_if_invalid), diff --git a/django/template/smartif.py b/django/template/smartif.py index 5b15a5a4765..0a917c2aaa4 100644 --- a/django/template/smartif.py +++ b/django/template/smartif.py @@ -1,6 +1,7 @@ """ Parser and utilities for the smart 'if' tag """ + # Using a simple top down parser, as described here: # http://effbot.org/zone/simple-top-down-parsing.htm. # 'led' = left denotation diff --git a/django/test/html.py b/django/test/html.py index 6da79d6fb24..33d1d4dafb4 100644 --- a/django/test/html.py +++ b/django/test/html.py @@ -1,4 +1,5 @@ """Compare two HTML documents.""" + import html from html.parser import HTMLParser diff --git a/django/urls/conf.py b/django/urls/conf.py index 40708028a38..bb61063d770 100644 --- a/django/urls/conf.py +++ b/django/urls/conf.py @@ -1,4 +1,5 @@ """Functions for use in URLsconfs.""" + from functools import partial from importlib import import_module diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py index 89ae18694cd..3607c84228a 100644 --- a/django/urls/resolvers.py +++ b/django/urls/resolvers.py @@ -5,6 +5,7 @@ a string) and returns a ResolverMatch object which provides access to all attributes of the resolved URL match. """ + import functools import inspect import re @@ -91,9 +92,11 @@ def __repr__(self): self.app_names, self.namespaces, self.route, - f", captured_kwargs={self.captured_kwargs!r}" - if self.captured_kwargs - else "", + ( + f", captured_kwargs={self.captured_kwargs!r}" + if self.captured_kwargs + else "" + ), f", extra_kwargs={self.extra_kwargs!r}" if self.extra_kwargs else "", ) ) diff --git a/django/utils/archive.py b/django/utils/archive.py index 71ec2d00155..56f34c00386 100644 --- a/django/utils/archive.py +++ b/django/utils/archive.py @@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ + import os import shutil import stat diff --git a/django/utils/cache.py b/django/utils/cache.py index cf797d0279a..3b014fbe514 100644 --- a/django/utils/cache.py +++ b/django/utils/cache.py @@ -14,6 +14,7 @@ An example: i18n middleware would need to distinguish caches by the "Accept-language" header. """ + import time from collections import defaultdict from hashlib import md5 diff --git a/django/utils/crypto.py b/django/utils/crypto.py index 1c0e7001c64..5134b854d63 100644 --- a/django/utils/crypto.py +++ b/django/utils/crypto.py @@ -1,6 +1,7 @@ """ Django's standard crypto functions and utilities. """ + import hashlib import hmac import secrets diff --git a/django/utils/dateformat.py b/django/utils/dateformat.py index a6c315e4cf2..a3274b901c3 100644 --- a/django/utils/dateformat.py +++ b/django/utils/dateformat.py @@ -10,6 +10,7 @@ 7th October 2003 11:39 >>> """ + import calendar from datetime import date, datetime, time from email.utils import format_datetime as format_datetime_rfc5322 diff --git a/django/utils/deconstruct.py b/django/utils/deconstruct.py index f8754c19741..2e5463a651d 100644 --- a/django/utils/deconstruct.py +++ b/django/utils/deconstruct.py @@ -42,9 +42,11 @@ def deconstruct(obj): "#serializing-values" % (name, module_name, get_docs_version()) ) return ( - path - if path and type(obj) is klass - else f"{obj.__class__.__module__}.{name}", + ( + path + if path and type(obj) is klass + else f"{obj.__class__.__module__}.{name}" + ), obj._constructor_args[0], obj._constructor_args[1], ) diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py index 31ca9a2db9a..3bd456ca687 100644 --- a/django/utils/feedgenerator.py +++ b/django/utils/feedgenerator.py @@ -21,6 +21,7 @@ For definitions of the different versions of RSS, see: https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004/02/04/incompatible-rss """ + import datetime import email from io import StringIO diff --git a/django/utils/jslex.py b/django/utils/jslex.py index 93a1a2e972f..fc46a686c7d 100644 --- a/django/utils/jslex.py +++ b/django/utils/jslex.py @@ -1,4 +1,5 @@ """JsLex: a lexer for JavaScript""" + # Originally from https://bitbucket.org/ned/jslex import re diff --git a/django/utils/regex_helper.py b/django/utils/regex_helper.py index 9ee82e1a9b7..b71298e3990 100644 --- a/django/utils/regex_helper.py +++ b/django/utils/regex_helper.py @@ -5,6 +5,7 @@ This is not, and is not intended to be, a complete reg-exp decompiler. It should be good enough for a large class of URLS, however. """ + import re from django.utils.functional import SimpleLazyObject diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index 0b3f78e4866..0618f021594 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -1,6 +1,7 @@ """ Internationalization support. """ + from contextlib import ContextDecorator from decimal import ROUND_UP, Decimal diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 872c80b00f7..a629528717f 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -1,4 +1,5 @@ """Translation helper functions.""" + import functools import gettext as gettext_module import os diff --git a/django/views/decorators/http.py b/django/views/decorators/http.py index 5d5dcbc7906..a4c1ebc31eb 100644 --- a/django/views/decorators/http.py +++ b/django/views/decorators/http.py @@ -1,6 +1,7 @@ """ Decorators for views based on HTTP headers. """ + import datetime from functools import wraps diff --git a/django/views/static.py b/django/views/static.py index df46c53093e..b24f0e30f9e 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -2,6 +2,7 @@ Views and functions for serving static files. These are only to be used during development, and SHOULD NOT be used in a production setting. """ + import mimetypes import posixpath from pathlib import Path diff --git a/docs/_ext/djangodocs.py b/docs/_ext/djangodocs.py index 7d55cb03336..77e24ff0eb6 100644 --- a/docs/_ext/djangodocs.py +++ b/docs/_ext/djangodocs.py @@ -1,6 +1,7 @@ """ Sphinx plugins for Django documentation. """ + import json import os import re diff --git a/docs/faq/install.txt b/docs/faq/install.txt index 388350b2d8f..01b59213570 100644 --- a/docs/faq/install.txt +++ b/docs/faq/install.txt @@ -63,9 +63,9 @@ download page `_. Typically, we will support a Python version up to and including the first Django LTS release whose security support ends after security support for that -version of Python ends. For example, Python 3.3 security support ended -September 2017 and Django 1.8 LTS security support ended April 2018. Therefore -Django 1.8 is the last version to support Python 3.3. +version of Python ends. For example, Python 3.9 security support ends in +October 2025 and Django 4.2 LTS security support ends in April 2026. Therefore +Django 4.2 is the last version to support Python 3.9. What Python version should I use with Django? ============================================= diff --git a/docs/howto/csrf.txt b/docs/howto/csrf.txt index 07f2e20a1c2..d40f4b4cb40 100644 --- a/docs/howto/csrf.txt +++ b/docs/howto/csrf.txt @@ -208,8 +208,7 @@ will require a CSRF token to be inserted you should use the @cache_page(60 * 15) @csrf_protect - def my_view(request): - ... + def my_view(request): ... If you are using class-based views, you can refer to :ref:`Decorating class-based views`. diff --git a/docs/howto/custom-file-storage.txt b/docs/howto/custom-file-storage.txt index 4e51548bc7b..661a343d045 100644 --- a/docs/howto/custom-file-storage.txt +++ b/docs/howto/custom-file-storage.txt @@ -14,8 +14,7 @@ You'll need to follow these steps: from django.core.files.storage import Storage - class MyStorage(Storage): - ... + class MyStorage(Storage): ... #. Django must be able to instantiate your storage system without any arguments. This means that any settings should be taken from ``django.conf.settings``:: diff --git a/docs/howto/custom-lookups.txt b/docs/howto/custom-lookups.txt index 61ec9295ebe..fc8e9288906 100644 --- a/docs/howto/custom-lookups.txt +++ b/docs/howto/custom-lookups.txt @@ -53,8 +53,7 @@ Lookup registration can also be done using a decorator pattern:: @Field.register_lookup - class NotEqualLookup(Lookup): - ... + class NotEqualLookup(Lookup): ... We can now use ``foo__ne`` for any field ``foo``. You will need to ensure that this registration happens before you try to create any querysets using it. You diff --git a/docs/howto/custom-management-commands.txt b/docs/howto/custom-management-commands.txt index 8bdfb1e38b9..d3775905d3f 100644 --- a/docs/howto/custom-management-commands.txt +++ b/docs/howto/custom-management-commands.txt @@ -146,8 +146,7 @@ decorator on your :meth:`~BaseCommand.handle` method:: ... @no_translations - def handle(self, *args, **options): - ... + def handle(self, *args, **options): ... Since translation deactivation requires access to configured settings, the decorator can't be used for commands that work without configured settings. @@ -305,7 +304,7 @@ the :meth:`~BaseCommand.handle` method must be implemented. It may return a string which will be printed to ``stdout`` (wrapped by ``BEGIN;`` and ``COMMIT;`` if :attr:`output_transaction` is ``True``). -.. method:: BaseCommand.check(app_configs=None, tags=None, display_num_errors=False) +.. method:: BaseCommand.check(app_configs=None, tags=None,display_num_errors=False, include_deployment_checks=False, fail_level=checks.ERROR, databases=None) Uses the system check framework to inspect the entire Django project for potential problems. Serious problems are raised as a :exc:`CommandError`; @@ -313,8 +312,12 @@ the :meth:`~BaseCommand.handle` method must be implemented. ``stdout``. If ``app_configs`` and ``tags`` are both ``None``, all system checks are - performed. ``tags`` can be a list of check tags, like ``compatibility`` or - ``models``. + performed except deployment and database related checks. ``tags`` can be a + list of check tags, like ``compatibility`` or ``models``. + + You can pass ``include_deployment_checks=True`` to also perform deployment + checks, and list of database aliases in the ``databases`` to run database + related checks against them. .. _ref-basecommand-subclasses: diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt index 1e7ac4f0bad..b4a15378968 100644 --- a/docs/howto/custom-model-fields.txt +++ b/docs/howto/custom-model-fields.txt @@ -338,24 +338,20 @@ Changing a custom field's base class You can't change the base class of a custom field because Django won't detect the change and make a migration for it. For example, if you start with:: - class CustomCharField(models.CharField): - ... + class CustomCharField(models.CharField): ... and then decide that you want to use ``TextField`` instead, you can't change the subclass like this:: - class CustomCharField(models.TextField): - ... + class CustomCharField(models.TextField): ... Instead, you must create a new custom field class and update your models to reference it:: - class CustomCharField(models.CharField): - ... + class CustomCharField(models.CharField): ... - class CustomTextField(models.TextField): - ... + class CustomTextField(models.TextField): ... As discussed in :ref:`removing fields `, you must retain the original ``CustomCharField`` class as long as you have diff --git a/docs/howto/custom-template-tags.txt b/docs/howto/custom-template-tags.txt index c7909c8a4bb..15bef9b5fbb 100644 --- a/docs/howto/custom-template-tags.txt +++ b/docs/howto/custom-template-tags.txt @@ -561,8 +561,7 @@ template loader, we'd register the tag like this:: # Here, register is a django.template.Library instance, as before @register.inclusion_tag("results.html") - def show_results(poll): - ... + def show_results(poll): ... Alternatively it is possible to register the inclusion tag using a :class:`django.template.Template` instance:: @@ -917,13 +916,11 @@ The ``tag()`` method takes two arguments: As with filter registration, it is also possible to use this as a decorator:: @register.tag(name="current_time") - def do_current_time(parser, token): - ... + def do_current_time(parser, token): ... @register.tag - def shout(parser, token): - ... + def shout(parser, token): ... If you leave off the ``name`` argument, as in the second example above, Django will use the function's name as the tag name. diff --git a/docs/howto/error-reporting.txt b/docs/howto/error-reporting.txt index 4e50c0e3092..50d1e0da386 100644 --- a/docs/howto/error-reporting.txt +++ b/docs/howto/error-reporting.txt @@ -177,8 +177,7 @@ filtered out of error reports in a production environment (that is, where do not provide any argument to the ``sensitive_variables`` decorator:: @sensitive_variables() - def my_function(): - ... + def my_function(): ... .. admonition:: When using multiple decorators @@ -191,8 +190,7 @@ filtered out of error reports in a production environment (that is, where @sensitive_variables("user", "pw", "cc") @some_decorator @another_decorator - def process_info(user): - ... + def process_info(user): ... .. versionchanged:: 5.0 @@ -229,8 +227,7 @@ filtered out of error reports in a production environment (that is, where do not provide any argument to the ``sensitive_post_parameters`` decorator:: @sensitive_post_parameters() - def my_view(request): - ... + def my_view(request): ... All POST parameters are systematically filtered out of error reports for certain :mod:`django.contrib.auth.views` views (``login``, diff --git a/docs/internals/contributing/writing-code/coding-style.txt b/docs/internals/contributing/writing-code/coding-style.txt index 6871d43d7be..49b69bf066f 100644 --- a/docs/internals/contributing/writing-code/coding-style.txt +++ b/docs/internals/contributing/writing-code/coding-style.txt @@ -201,8 +201,7 @@ Imports CONSTANT = "foo" - class Example: - ... + class Example: ... * Use convenience imports whenever available. For example, do this :: @@ -239,13 +238,11 @@ View style Do this:: - def my_view(request, foo): - ... + def my_view(request, foo): ... Don't do this:: - def my_view(req, foo): - ... + def my_view(req, foo): ... Model style =========== diff --git a/docs/internals/contributing/writing-code/submitting-patches.txt b/docs/internals/contributing/writing-code/submitting-patches.txt index be031f1f68c..72c986cfc72 100644 --- a/docs/internals/contributing/writing-code/submitting-patches.txt +++ b/docs/internals/contributing/writing-code/submitting-patches.txt @@ -190,8 +190,7 @@ level: @ignore_warnings(category=RemovedInDjangoXXWarning) - def test_foo(self): - ... + def test_foo(self): ... #) For an entire test case:: @@ -200,8 +199,7 @@ level: @ignore_warnings(category=RemovedInDjangoXXWarning) - class MyDeprecatedTests(unittest.TestCase): - ... + class MyDeprecatedTests(unittest.TestCase): ... You should also add a test for the deprecation warning:: diff --git a/docs/internals/security.txt b/docs/internals/security.txt index 373012b707e..55300b01e17 100644 --- a/docs/internals/security.txt +++ b/docs/internals/security.txt @@ -84,24 +84,24 @@ upcoming security release, as well as the severity of the issues. This is to aid organizations that need to ensure they have staff available to handle triaging our announcement and upgrade Django as needed. Severity levels are: -**High**: +* **High** -* Remote code execution -* SQL injection + * Remote code execution + * SQL injection -**Moderate**: +* **Moderate** -* Cross site scripting (XSS) -* Cross site request forgery (CSRF) -* Denial-of-service attacks -* Broken authentication + * Cross site scripting (XSS) + * Cross site request forgery (CSRF) + * Denial-of-service attacks + * Broken authentication -**Low**: +* **Low** -* Sensitive data exposure -* Broken session management -* Unvalidated redirects/forwards -* Issues requiring an uncommon configuration option + * Sensitive data exposure + * Broken session management + * Unvalidated redirects/forwards + * Issues requiring an uncommon configuration option Second, we notify a list of :ref:`people and organizations `, primarily composed of operating-system vendors and diff --git a/docs/intro/contributing.txt b/docs/intro/contributing.txt index 652bca0cb25..06230b8ee30 100644 --- a/docs/intro/contributing.txt +++ b/docs/intro/contributing.txt @@ -27,8 +27,8 @@ For this tutorial, we expect that you have at least a basic understanding of how Django works. This means you should be comfortable going through the existing tutorials on :doc:`writing your first Django app`. In addition, you should have a good understanding of Python itself. But if you -don't, `Dive Into Python`__ is a fantastic (and free) online book for -beginning Python programmers. +don't, `Dive Into Python`_ is a fantastic (and free) online book for beginning +Python programmers. Those of you who are unfamiliar with version control systems and Trac will find that this tutorial and its links include just enough information to get started. @@ -45,8 +45,8 @@ so that it can be of use to the widest audience. `#django-dev on irc.libera.chat`__ to chat with other Django users who might be able to help. -__ https://diveinto.org/python3/table-of-contents.html __ https://web.libera.chat/#django-dev +.. _Dive Into Python: https://diveintopython3.net/ .. _Django Forum: https://forum.djangoproject.com/ What does this tutorial cover? @@ -350,7 +350,7 @@ This test checks that the ``make_toast()`` returns ``'toast'``. * After reading those, if you want something a little meatier to sink your teeth into, there's always the Python :mod:`unittest` documentation. -__ https://diveinto.org/python3/unit-testing.html +__ https://diveintopython3.net/unit-testing.html Running your new test --------------------- diff --git a/docs/intro/index.txt b/docs/intro/index.txt index ca4836367f5..a68d4876b70 100644 --- a/docs/intro/index.txt +++ b/docs/intro/index.txt @@ -32,10 +32,12 @@ place: read this material to quickly get up and running. `list of Python resources for non-programmers`_ If you already know a few other languages and want to get up to speed with - Python quickly, we recommend `Dive Into Python`_. If that's not quite your - style, there are many other `books about Python`_. + Python quickly, we recommend referring the official + `Python documentation`_, which provides comprehensive and authoritative + information about the language, as well as links to other resources such as + a list of `books about Python`_. .. _python: https://www.python.org/ .. _list of Python resources for non-programmers: https://wiki.python.org/moin/BeginnersGuide/NonProgrammers - .. _Dive Into Python: https://diveinto.org/python3/table-of-contents.html + .. _Python documentation: https://docs.python.org/3/ .. _books about Python: https://wiki.python.org/moin/PythonBooks diff --git a/docs/intro/reusable-apps.txt b/docs/intro/reusable-apps.txt index 19d9063edd2..0ca63830ea0 100644 --- a/docs/intro/reusable-apps.txt +++ b/docs/intro/reusable-apps.txt @@ -76,7 +76,7 @@ After the previous tutorials, our project should look like this: static/ polls/ images/ - background.gif + background.png style.css templates/ polls/ @@ -121,16 +121,17 @@ Python *packaging* refers to preparing your app in a specific format that can be easily installed and used. Django itself is packaged very much like this. For a small app like polls, this process isn't too difficult. -#. First, create a parent directory for ``polls``, outside of your Django +#. First, create a parent directory for the package, outside of your Django project. Call this directory ``django-polls``. .. admonition:: Choosing a name for your app - When choosing a name for your package, check resources like PyPI to avoid - naming conflicts with existing packages. It's often useful to prepend - ``django-`` to your module name when creating a package to distribute. - This helps others looking for Django apps identify your app as Django - specific. + When choosing a name for your package, check PyPI to avoid naming + conflicts with existing packages. We recommend using a ``django-`` + prefix for package names, to identify your package as specific to + Django, and a corresponding ``django_`` prefix for your module name. For + example, the ``django-ratelimit`` package contains the + ``django_ratelimit`` module. Application labels (that is, the final part of the dotted path to application packages) *must* be unique in :setting:`INSTALLED_APPS`. @@ -138,19 +139,35 @@ this. For a small app like polls, this process isn't too difficult. `, for example ``auth``, ``admin``, or ``messages``. -#. Move the ``polls`` directory into the ``django-polls`` directory. +#. Move the ``polls`` directory into ``django-polls`` directory, and rename it + to ``django_polls``. + +#. Edit ``django_polls/apps.py`` so that :attr:`~.AppConfig.name` refers to the + new module name and add :attr:`~.AppConfig.label` to give a short name for + the app: + + .. code-block:: python + :caption: ``django-polls/django_polls/apps.py`` + + from django.apps import AppConfig + + + class PollsConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "django_polls" + label = "polls" #. Create a file ``django-polls/README.rst`` with the following contents: .. code-block:: rst :caption: ``django-polls/README.rst`` - ===== - Polls - ===== + ============ + django-polls + ============ - Polls is a Django app to conduct web-based polls. For each question, - visitors can choose between a fixed number of answers. + django-polls is a Django app to conduct web-based polls. For each + question, visitors can choose between a fixed number of answers. Detailed documentation is in the "docs" directory. @@ -161,19 +178,18 @@ this. For a small app like polls, this process isn't too difficult. INSTALLED_APPS = [ ..., - "polls", + "django_polls", ] 2. Include the polls URLconf in your project urls.py like this:: - path("polls/", include("polls.urls")), + path("polls/", include("django_polls.urls")), - 3. Run ``python manage.py migrate`` to create the polls models. + 3. Run ``python manage.py migrate`` to create the models. - 4. Start the development server and visit http://127.0.0.1:8000/admin/ - to create a poll (you'll need the Admin app enabled). + 4. Start the development server and visit the admin to create a poll. - 5. Visit http://127.0.0.1:8000/polls/ to participate in the poll. + 5. Visit the ``/polls/`` URL to participate in the poll. #. Create a ``django-polls/LICENSE`` file. Choosing a license is beyond the scope of this tutorial, but suffice it to say that code released publicly @@ -251,8 +267,8 @@ this. For a small app like polls, this process isn't too difficult. include LICENSE include README.rst - recursive-include polls/static * - recursive-include polls/templates * + recursive-include django_polls/static * + recursive-include django_polls/templates * #. It's optional, but recommended, to include detailed documentation with your app. Create an empty directory ``django-polls/docs`` for future @@ -266,8 +282,8 @@ this. For a small app like polls, this process isn't too difficult. you add some files to it. Many Django apps also provide their documentation online through sites like `readthedocs.org `_. -#. Try building your package with ``python setup.py sdist`` (run from inside - ``django-polls``). This creates a directory called ``dist`` and builds your +#. Try building your package by running ``python setup.py sdist`` inside + ``django-polls``. This creates a directory called ``dist`` and builds your new package, ``django-polls-0.1.tar.gz``. For more information on packaging, see Python's `Tutorial on Packaging and @@ -299,14 +315,21 @@ working. We'll now fix this by installing our new ``django-polls`` package. python -m pip install --user django-polls/dist/django-polls-0.1.tar.gz -#. With luck, your Django project should now work correctly again. Run the - server again to confirm this. +#. Update ``mysite/settings.py`` to point to the new module name:: -#. To uninstall the package, use pip: + INSTALLED_APPS = [ + "django_polls.apps.PollsConfig", + ..., + ] - .. code-block:: shell +#. Update ``mysite/urls.py`` to point to the new module name:: + + urlpatterns = [ + path("polls/", include("django_polls.urls")), + ..., + ] - python -m pip uninstall django-polls +#. Run the development server to confirm the project continues to work. Publishing your app =================== @@ -326,7 +349,7 @@ the world! If this wasn't just an example, you could now: Installing Python packages with a virtual environment ===================================================== -Earlier, we installed the polls app as a user library. This has some +Earlier, we installed ``django-polls`` as a user library. This has some disadvantages: * Modifying the user libraries can affect other Python software on your system. diff --git a/docs/intro/tutorial03.txt b/docs/intro/tutorial03.txt index 04bd83ae52f..3d59809a0c1 100644 --- a/docs/intro/tutorial03.txt +++ b/docs/intro/tutorial03.txt @@ -106,7 +106,7 @@ Wire these new views into the ``polls.urls`` module by adding the following ] Take a look in your browser, at "/polls/34/". It'll run the ``detail()`` -method and display whatever ID you provide in the URL. Try +function and display whatever ID you provide in the URL. Try "/polls/34/results/" and "/polls/34/vote/" too -- these will display the placeholder results and voting pages. @@ -401,7 +401,7 @@ template, the link was partially hardcoded like this: The problem with this hardcoded, tightly-coupled approach is that it becomes challenging to change URLs on projects with a lot of templates. However, since -you defined the name argument in the :func:`~django.urls.path` functions in +you defined the ``name`` argument in the :func:`~django.urls.path` functions in the ``polls.urls`` module, you can remove a reliance on specific URL paths defined in your url configurations by using the ``{% url %}`` template tag: diff --git a/docs/intro/tutorial04.txt b/docs/intro/tutorial04.txt index 13a76188bb9..65dc132a947 100644 --- a/docs/intro/tutorial04.txt +++ b/docs/intro/tutorial04.txt @@ -309,7 +309,8 @@ views and use Django's generic views instead. To do so, open the def vote(request, question_id): - ... # same as above, no changes needed. + # same as above, no changes needed. + ... Each generic view needs to know what model it will be acting upon. This is provided using either the ``model`` attribute (in this example, ``model = diff --git a/docs/intro/tutorial07.txt b/docs/intro/tutorial07.txt index 7810ad7fad0..8cb5dd5d5a2 100644 --- a/docs/intro/tutorial07.txt +++ b/docs/intro/tutorial07.txt @@ -174,8 +174,7 @@ tabular way of displaying inline related objects. To use it, change the .. code-block:: python :caption: ``polls/admin.py`` - class ChoiceInline(admin.TabularInline): - ... + class ChoiceInline(admin.TabularInline): ... With that ``TabularInline`` (instead of ``StackedInline``), the related objects are displayed in a more compact, table-based format: @@ -367,7 +366,10 @@ a section of code like: .. code-block:: html+django {% block branding %} -
Polls Administration
+ + {% if user.is_anonymous %} + {% include "admin/color_theme_toggle.html" %} + {% endif %} {% endblock %} We use this approach to teach you how to override templates. In an actual diff --git a/docs/misc/design-philosophies.txt b/docs/misc/design-philosophies.txt index 207685d5569..95ba3d86cd3 100644 --- a/docs/misc/design-philosophies.txt +++ b/docs/misc/design-philosophies.txt @@ -254,10 +254,6 @@ enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions. The :ref:`Django Template Language (DTL) ` aims to avoid advanced logic. -The Django template system recognizes that templates are most often written by -*designers*, not *programmers*, and therefore should not assume Python -knowledge. - Safety and security ------------------- diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index fef582f2df4..25e98c3b949 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -751,8 +751,7 @@ subclass:: like:: @admin.display(ordering="-first_name") - def colored_first_name(self): - ... + def colored_first_name(self): ... The ``ordering`` argument supports query lookups to sort by values on related models. This example includes an "author first name" column in @@ -3132,8 +3131,7 @@ returns a site instance. from django.contrib import admin - class MyAdminSite(admin.AdminSite): - ... + class MyAdminSite(admin.AdminSite): ... .. code-block:: python :caption: ``myproject/apps.py`` @@ -3471,5 +3469,4 @@ The ``staff_member_required`` decorator @staff_member_required - def my_view(request): - ... + def my_view(request): ... diff --git a/docs/ref/contrib/auth.txt b/docs/ref/contrib/auth.txt index 482eed231b4..953c31a6ae5 100644 --- a/docs/ref/contrib/auth.txt +++ b/docs/ref/contrib/auth.txt @@ -188,6 +188,12 @@ Methods You may need this if authentication for your application takes place against an existing external source such as an LDAP directory. + .. admonition:: Password reset restriction + + Users having an unusable password will not able to request a + password reset email via + :class:`~django.contrib.auth.views.PasswordResetView`. + .. method:: has_usable_password() Returns ``False`` if diff --git a/docs/ref/contrib/gis/feeds.txt b/docs/ref/contrib/gis/feeds.txt index 9ae9d4f03a4..3f17a685741 100644 --- a/docs/ref/contrib/gis/feeds.txt +++ b/docs/ref/contrib/gis/feeds.txt @@ -40,18 +40,14 @@ API Reference item_geometry = ... # Also a function with no arguments - def geometry(self): - ... + def geometry(self): ... - def item_geometry(self): - ... + def item_geometry(self): ... # And as a function with a single argument - def geometry(self, obj): - ... + def geometry(self, obj): ... - def item_geometry(self, item): - ... + def item_geometry(self, item): ... .. method:: geometry(obj) diff --git a/docs/ref/contrib/gis/tutorial.txt b/docs/ref/contrib/gis/tutorial.txt index d1c4cdb8e49..eb62df56a86 100644 --- a/docs/ref/contrib/gis/tutorial.txt +++ b/docs/ref/contrib/gis/tutorial.txt @@ -252,7 +252,7 @@ model: This command should produce the following output: -.. console:: +.. code-block:: sql BEGIN; -- @@ -686,12 +686,13 @@ __ https://spatialreference.org/ref/epsg/32140/ .. code-block:: pycon - from django.db import connection - # or if you're querying a non-default database: - from django.db import connections - connection = connections['your_gis_db_alias'] - - City.objects.raw('SELECT id, name, %s as point from myapp_city' % (connection.ops.select % 'point')) + >>> from django.db import connection + >>> # or if you're querying a non-default database: + >>> from django.db import connections + >>> connection = connections["your_gis_db_alias"] + >>> City.objects.raw( + ... "SELECT id, name, %s as point from myapp_city" % (connection.ops.select % "point") + ... ) You should only use raw queries when you know exactly what you're doing. diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt index f859f513773..92b1f40898c 100644 --- a/docs/ref/databases.txt +++ b/docs/ref/databases.txt @@ -164,8 +164,14 @@ password from the `password file`_, you must specify them in the localhost:5432:NAME:USER:PASSWORD +The PostgreSQL backend passes the content of :setting:`OPTIONS` as keyword +arguments to the connection constructor, allowing for more advanced control +of driver behavior. All available `parameters`_ are described in detail in the +PostgreSQL documentation. + .. _connection service file: https://www.postgresql.org/docs/current/libpq-pgservice.html .. _password file: https://www.postgresql.org/docs/current/libpq-pgpass.html +.. _parameters: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS .. warning:: diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index f533aa11dea..59c731113cb 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -1804,9 +1804,9 @@ allows for the following options by default: .. django-admin-option:: --pythonpath PYTHONPATH -Adds the given filesystem path to the Python `import search path`_. If this -isn't provided, ``django-admin`` will use the :envvar:`PYTHONPATH` environment -variable. +Adds the given filesystem path to the Python :py:data:`sys.path` module +attribute. If this isn't provided, ``django-admin`` will use the +:envvar:`PYTHONPATH` environment variable. This option is unnecessary in ``manage.py``, because it takes care of setting the Python path for you. @@ -1817,8 +1817,6 @@ Example usage: django-admin migrate --pythonpath='/home/djangoprojects/myproject' -.. _import search path: https://diveinto.org/python3/your-first-python-program.html#importsearchpath - .. django-admin-option:: --settings SETTINGS Specifies the settings module to use. The settings module should be in Python diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index 7bec9b120b9..28cd452c4e8 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -909,7 +909,7 @@ It's possible to customize that character, or omit it entirely, using the
>>> f = ContactForm(auto_id="id_for_%s", label_suffix=" ->") >>> print(f) -
+
diff --git a/docs/ref/logging.txt b/docs/ref/logging.txt index b11fb752f79..fa07422cd51 100644 --- a/docs/ref/logging.txt +++ b/docs/ref/logging.txt @@ -204,6 +204,39 @@ all database queries. Support for logging transaction management queries (``BEGIN``, ``COMMIT``, and ``ROLLBACK``) was added. +.. _django-utils-autoreloader-logger: + +``django.utils.autoreload`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Log messages related to automatic code reloading during the execution of the +Django development server. This logger generates an ``INFO`` message upon +detecting a modification in a source code file and may produce ``WARNING`` +messages during filesystem inspection and event subscription processes. + +.. _django-contrib-gis-logger: + +``django.contrib.gis`` +~~~~~~~~~~~~~~~~~~~~~~ + +Log messages related to :doc:`contrib/gis/index` at various points: during the +loading of external GeoSpatial libraries (GEOS, GDAL, etc.) and when reporting +errors. Each ``ERROR`` log record includes the caught exception and relevant +contextual data. + +.. _django-dispatch-logger: + +``django.dispatch`` +~~~~~~~~~~~~~~~~~~~ + +This logger is used in :doc:`signals`, specifically within the +:mod:`~django.dispatch.Signal` class, to report issues when dispatching a +signal to a connected receiver. The ``ERROR`` log record includes the caught +exception as ``exc_info`` and adds the following extra context: + +* ``receiver``: The name of the receiver. +* ``err``: The exception that occurred when calling the receiver. + .. _django-security-logger: ``django.security.*`` diff --git a/docs/ref/models/constraints.txt b/docs/ref/models/constraints.txt index efe63a8ac18..cc308cedf22 100644 --- a/docs/ref/models/constraints.txt +++ b/docs/ref/models/constraints.txt @@ -229,7 +229,8 @@ For example:: will allow filtering on ``room`` and ``date``, also selecting ``full_name``, while fetching data only from the index. -``include`` is supported only on PostgreSQL. +Unique constraints with non-key columns are ignored for databases besides +PostgreSQL. Non-key columns have the same database restrictions as :attr:`Index.include`. @@ -272,7 +273,8 @@ For example:: creates a unique constraint that only allows one row to store a ``NULL`` value in the ``ordering`` column. -``nulls_distinct`` is ignored for databases besides PostgreSQL 15+. +Unique constraints with ``nulls_distinct`` are ignored for databases besides +PostgreSQL 15+. ``violation_error_code`` ------------------------ diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt index a5edfa550a5..63847a2328e 100644 --- a/docs/ref/models/expressions.txt +++ b/docs/ref/models/expressions.txt @@ -92,7 +92,7 @@ Some examples >>> Company.objects.order_by("name__length") # Boolean expression can be used directly in filters. - >>> from django.db.models import Exists + >>> from django.db.models import Exists, OuterRef >>> Company.objects.filter( ... Exists(Employee.objects.filter(company=OuterRef("pk"), salary__gt=10)) ... ) @@ -757,9 +757,7 @@ should avoid them if possible. your SQL with user-provided data. You also must not quote placeholders in the SQL string. This example is - vulnerable to SQL injection because of the quotes around ``%s``: - - .. code-block:: pycon + vulnerable to SQL injection because of the quotes around ``%s``:: RawSQL("select col from sometable where othercol = '%s'") # unsafe! diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index 3148f8ace52..49ee126acac 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -1090,13 +1090,12 @@ Custom response classes ~~~~~~~~~~~~~~~~~~~~~~~ If you find yourself needing a response class that Django doesn't provide, you -can create it with the help of :py:class:`http.HTTPStatus`. For example: - -.. code-block:: pycon +can create it with the help of :py:class:`http.HTTPStatus`. For example:: from http import HTTPStatus from django.http import HttpResponse + class HttpResponseNoContent(HttpResponse): status_code = HTTPStatus.NO_CONTENT diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 28d72e356e4..a7b789c3f69 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -273,8 +273,8 @@ See :doc:`/topics/cache`. Default: ``600`` -The default number of seconds to cache a page for the :ref:`cache middleware -`. +The default integer number of seconds to cache a page for the +:ref:`cache middleware `. See :doc:`/topics/cache`. @@ -422,8 +422,7 @@ A dotted path to the view function to be used when an incoming request is rejected by the :doc:`CSRF protection `. The function should have this signature:: - def csrf_failure(request, reason=""): - ... + def csrf_failure(request, reason=""): ... where ``reason`` is a short message (intended for developers or logging, not for end users) indicating the reason the request was rejected. It should return @@ -663,8 +662,10 @@ A string representing the time zone for this database connection or ``None``. This inner option of the :setting:`DATABASES` setting accepts the same values as the general :setting:`TIME_ZONE` setting. -When :setting:`USE_TZ` is ``True`` and this option is set, reading datetimes -from the database returns aware datetimes in this time zone instead of UTC. +When :setting:`USE_TZ` is ``True``, reading datetimes from the database +returns aware datetimes with the timezone set to this option's value if not +``None``, or to UTC otherwise. + When :setting:`USE_TZ` is ``False``, it is an error to set this option. * If the database backend doesn't support time zones (e.g. SQLite, MySQL, @@ -687,13 +688,18 @@ When :setting:`USE_TZ` is ``False``, it is an error to set this option. third-party systems connect to the same database and expect to find datetimes in local time, then you must set this option. -* If the database backend supports time zones (e.g. PostgreSQL), the - ``TIME_ZONE`` option is very rarely needed. It can be changed at any time; - the database takes care of converting datetimes to the desired time zone. +* If the database backend supports time zones (e.g., PostgreSQL), then the + database connection's time zone is set to this value. - Setting the time zone of the database connection may be useful for running - raw SQL queries involving date/time functions provided by the database, such - as ``date_trunc``, because their results depend on the time zone. + Although setting the ``TIME_ZONE`` option is very rarely needed, there are + situations where it becomes necessary. Specifically, it's recommended to + match the general :setting:`TIME_ZONE` setting when dealing with raw queries + involving date/time functions like PostgreSQL's ``date_trunc()`` or + ``generate_series()``, especially when generating time-based series that + transition daylight savings. + + This value can be changed at any time, the database will handle the + conversion of datetimes to the configured time zone. However, this has a downside: receiving all datetimes in local time makes datetime arithmetic more tricky — you must account for possible offset @@ -1354,9 +1360,12 @@ specify a particular storage system. See :doc:`/topics/files`. Default: ``'webmaster@localhost'`` -Default email address to use for various automated correspondence from the -site manager(s). This doesn't include error messages sent to :setting:`ADMINS` -and :setting:`MANAGERS`; for that, see :setting:`SERVER_EMAIL`. +Default email address for automated correspondence from the site manager(s). +This address is used in the ``From:`` header of outgoing emails and can take +any format valid in the chosen email sending protocol. + +This doesn't affect error messages sent to :setting:`ADMINS` and +:setting:`MANAGERS`. See :setting:`SERVER_EMAIL` for that. .. setting:: DEFAULT_INDEX_TABLESPACE @@ -1398,7 +1407,7 @@ This is only used if ``CommonMiddleware`` is installed (see Default: ``'``:class:`django.core.mail.backends.smtp.EmailBackend`\ ``'`` The backend to use for sending emails. For the list of available backends see -:doc:`/topics/email`. +:ref:`topic-email-backends`. .. setting:: EMAIL_FILE_PATH @@ -2546,7 +2555,9 @@ example, to define a YAML serializer, use:: Default: ``'root@localhost'`` The email address that error messages come from, such as those sent to -:setting:`ADMINS` and :setting:`MANAGERS`. +:setting:`ADMINS` and :setting:`MANAGERS`. This address is used in the +``From:`` header and can take any format valid in the chosen email sending +protocol. .. admonition:: Why are my emails sent from a different address? diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 536f9259bc9..8a2b7141353 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -524,11 +524,10 @@ Use of both ``and`` and ``or`` clauses within the same tag is allowed, with {% if athlete_list and coach_list or cheerleader_list %} -will be interpreted like: +will be interpreted like:: -.. code-block:: pycon - - if (athlete_list and coach_list) or cheerleader_list + if (athlete_list and coach_list) or cheerleader_list: + ... Use of actual parentheses in the :ttag:`if` tag is invalid syntax. If you need them to indicate precedence, you should use nested :ttag:`if` tags. @@ -2441,8 +2440,8 @@ individual elements of the sequence. Returns a slice of the list. -Uses the same syntax as Python's list slicing. See -https://diveinto.org/python3/native-datatypes.html#slicinglists for an +Uses the same syntax as Python's list slicing. See the `Python documentation +`_ for an introduction. Example: diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index acbe5d51a62..84e33d5d410 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -469,8 +469,7 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004 class Person(models.Model): @cached_property - def friends(self): - ... + def friends(self): ... Note that as the method is now a property, in Python code it will need to be accessed appropriately:: @@ -552,8 +551,7 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004 # Or more succinctly: @keep_lazy(str) - def fancy_utility_function(s, *args, **kwargs): - ... + def fancy_utility_function(s, *args, **kwargs): ... The ``keep_lazy()`` decorator takes a number of extra arguments (``*args``) specifying the type(s) that the original function can return. A common @@ -578,14 +576,12 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004 # Our previous example was: @keep_lazy(str) - def fancy_utility_function(s, *args, **kwargs): - ... + def fancy_utility_function(s, *args, **kwargs): ... # Which can be rewritten as: @keep_lazy_text - def fancy_utility_function(s, *args, **kwargs): - ... + def fancy_utility_function(s, *args, **kwargs): ... ``django.utils.html`` ===================== diff --git a/docs/releases/1.0-porting-guide.txt b/docs/releases/1.0-porting-guide.txt index f0ed8f41690..145334c2383 100644 --- a/docs/releases/1.0-porting-guide.txt +++ b/docs/releases/1.0-porting-guide.txt @@ -144,8 +144,7 @@ example: Old (0.96):: - class Parent(models.Model): - ... + class Parent(models.Model): ... class Child(models.Model): diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index b5213ee2072..d98fad2c662 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -732,8 +732,7 @@ custom lookup for it. For example:: from django.db.models.lookups import Exact - class MyField(Field): - ... + class MyField(Field): ... class MyFieldExact(Exact): diff --git a/docs/releases/1.2.txt b/docs/releases/1.2.txt index de3ed69a70a..526bb1d66e2 100644 --- a/docs/releases/1.2.txt +++ b/docs/releases/1.2.txt @@ -455,17 +455,13 @@ database-compatible values. A custom field might look something like:: class CustomModelField(models.Field): ... - def db_type(self): - ... + def db_type(self): ... - def get_db_prep_save(self, value): - ... + def get_db_prep_save(self, value): ... - def get_db_prep_value(self, value): - ... + def get_db_prep_value(self, value): ... - def get_db_prep_lookup(self, lookup_type, value): - ... + def get_db_prep_lookup(self, lookup_type, value): ... In 1.2, these three methods have undergone a change in prototype, and two extra methods have been introduced:: @@ -473,23 +469,17 @@ two extra methods have been introduced:: class CustomModelField(models.Field): ... - def db_type(self, connection): - ... + def db_type(self, connection): ... - def get_prep_value(self, value): - ... + def get_prep_value(self, value): ... - def get_prep_lookup(self, lookup_type, value): - ... + def get_prep_lookup(self, lookup_type, value): ... - def get_db_prep_save(self, value, connection): - ... + def get_db_prep_save(self, value, connection): ... - def get_db_prep_value(self, value, connection, prepared=False): - ... + def get_db_prep_value(self, value, connection, prepared=False): ... - def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False): - ... + def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False): ... These changes are required to support multiple databases -- ``db_type`` and ``get_db_prep_*`` can no longer make any assumptions diff --git a/docs/releases/3.2.24.txt b/docs/releases/3.2.24.txt new file mode 100644 index 00000000000..67be0f65d18 --- /dev/null +++ b/docs/releases/3.2.24.txt @@ -0,0 +1,13 @@ +=========================== +Django 3.2.24 release notes +=========================== + +*February 6, 2024* + +Django 3.2.24 fixes a security issue with severity "moderate" in 3.2.23. + +CVE-2024-24680: Potential denial-of-service in ``intcomma`` template filter +=========================================================================== + +The ``intcomma`` template filter was subject to a potential denial-of-service +attack when used with very long strings. diff --git a/docs/releases/4.2.10.txt b/docs/releases/4.2.10.txt new file mode 100644 index 00000000000..7cdfa698144 --- /dev/null +++ b/docs/releases/4.2.10.txt @@ -0,0 +1,13 @@ +=========================== +Django 4.2.10 release notes +=========================== + +*February 6, 2024* + +Django 4.2.10 fixes a security issue with severity "moderate" in 4.2.9. + +CVE-2024-24680: Potential denial-of-service in ``intcomma`` template filter +=========================================================================== + +The ``intcomma`` template filter was subject to a potential denial-of-service +attack when used with very long strings. diff --git a/docs/releases/4.2.9.txt b/docs/releases/4.2.9.txt new file mode 100644 index 00000000000..9a1e7dc1985 --- /dev/null +++ b/docs/releases/4.2.9.txt @@ -0,0 +1,13 @@ +========================== +Django 4.2.9 release notes +========================== + +*January 2, 2024* + +Django 4.2.9 fixes a bug in 4.2.8. + +Bugfixes +======== + +* Fixed a regression in Django 4.2.8 where admin fields on the same line could + overflow the page and become non-interactive (:ticket:`35012`). diff --git a/docs/releases/5.0.1.txt b/docs/releases/5.0.1.txt new file mode 100644 index 00000000000..8d2bd6a1873 --- /dev/null +++ b/docs/releases/5.0.1.txt @@ -0,0 +1,38 @@ +========================== +Django 5.0.1 release notes +========================== + +*January 2, 2024* + +Django 5.0.1 fixes several bugs in 5.0. + +Bugfixes +======== + +* Reallowed, following a regression in Django 5.0, using a foreign key to a + model with a primary key that is not ``AutoField`` in + :attr:`.ModelAdmin.list_filter` (:ticket:`35020`). + +* Fixed a long standing bug in handling the ``RETURNING INTO`` clause that + caused a crash when creating a model instance with a ``GeneratedField`` which + ``output_field`` had backend-specific converters (:ticket:`35024`). + +* Fixed a regression in Django 5.0 that caused a crash of ``Model.save()`` for + models with both ``GeneratedField`` and ``ForeignKey`` fields + (:ticket:`35019`). + +* Fixed a bug in Django 5.0 that caused a migration crash on Oracle < 23c when + adding a ``GeneratedField`` with ``output_field=BooleanField`` + (:ticket:`35018`). + +* Fixed a regression in Django 5.0 where admin fields on the same line could + overflow the page and become non-interactive (:ticket:`35012`). + +* Added compatibility for ``oracledb`` 2.0.0 (:ticket:`35054`). + +* Fixed a regression in Django 5.0 where querysets referenced incorrect field + names from ``FilteredRelation()`` (:ticket:`35050`). + +* Fixed a regression in Django 5.0 that caused a system check crash when + ``ModelAdmin.filter_horizontal`` or ``filter_vertical`` contained a reverse + many-to-many relation with ``related_name`` (:ticket:`35056`). diff --git a/docs/releases/5.0.2.txt b/docs/releases/5.0.2.txt new file mode 100644 index 00000000000..1da6dc02d93 --- /dev/null +++ b/docs/releases/5.0.2.txt @@ -0,0 +1,49 @@ +========================== +Django 5.0.2 release notes +========================== + +*February 6, 2024* + +Django 5.0.2 fixes a security issue with severity "moderate" and several bugs +in 5.0.1. Also, the latest string translations from Transifex are incorporated. + +CVE-2024-24680: Potential denial-of-service in ``intcomma`` template filter +=========================================================================== + +The ``intcomma`` template filter was subject to a potential denial-of-service +attack when used with very long strings. + +Bugfixes +======== + +* Reallowed, following a regression in Django 5.0.1, filtering against local + foreign keys not included in :attr:`.ModelAdmin.list_filter` + (:ticket:`35087`). + +* Fixed a regression in Django 5.0 where links in the admin had an incorrect + color (:ticket:`35121`). + +* Fixed a bug in Django 5.0 that caused a crash of ``Model.full_clean()`` on + models with a ``GeneratedField`` (:ticket:`35127`). + +* Fixed a regression in Django 5.0 that caused a crash of + ``FilteredRelation()`` with querysets as right-hand sides (:ticket:`35135`). + ``FilteredRelation()`` now raises a ``ValueError`` on querysets as right-hand + sides. + +* Fixed a regression in Django 5.0 that caused a crash of the ``dumpdata`` + management command when a base queryset used ``prefetch_related()`` + (:ticket:`35159`). + +* Fixed a regression in Django 5.0 that caused the ``request_finished`` signal to + sometimes not be fired when running Django through an ASGI server, resulting + in potential resource leaks (:ticket:`35059`). + +* Fixed a bug in Django 5.0 that caused a migration crash on MySQL when adding + a ``BinaryField``, ``TextField``, ``JSONField``, or ``GeometryField`` with a + ``db_default`` (:ticket:`35162`). + +* Fixed a bug in Django 5.0 that caused a migration crash on models with a + literal ``db_default`` of a complex type such as ``dict`` instance of a + ``JSONField``. Running ``makemigrations`` might generate no-op ``AlterField`` + operations for fields using ``db_default`` (:ticket:`35149`). diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt index 4c86337b745..a10c9d280a9 100644 --- a/docs/releases/5.0.txt +++ b/docs/releases/5.0.txt @@ -508,6 +508,12 @@ Django < 5.0 should be replaced with a ``UUIDField`` subclass backed by def db_type(self, connection): return "char(32)" + def get_db_prep_value(self, value, connection, prepared=False): + value = super().get_db_prep_value(value, connection, prepared) + if value is not None: + value = value.hex + return value + For example:: class MyModel(models.Model): @@ -515,9 +521,7 @@ For example:: Should become:: - class Char32UUIDField(models.UUIDField): - def db_type(self, connection): - return "char(32)" + class Char32UUIDField(models.UUIDField): ... class MyModel(models.Model): @@ -584,6 +588,11 @@ Miscellaneous * The minimum supported version of ``docutils`` is increased to 0.19. +* Filtering querysets against overflowing integer values now always returns an + empty queryset. As a consequence, you may need to use ``ExpressionWrapper()`` + to :ref:`explicitly wrap ` arithmetic against + integer fields in such cases. + .. _deprecated-features-5.0: Features deprecated in 5.0 diff --git a/docs/releases/index.txt b/docs/releases/index.txt index 63f36464a0a..ba6d7fbd460 100644 --- a/docs/releases/index.txt +++ b/docs/releases/index.txt @@ -25,6 +25,8 @@ versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 5.0.2 + 5.0.1 5.0 4.2 release @@ -33,6 +35,8 @@ versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 4.2.10 + 4.2.9 4.2.8 4.2.7 4.2.6 @@ -85,6 +89,7 @@ versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 3.2.24 3.2.23 3.2.22 3.2.21 diff --git a/docs/topics/async.txt b/docs/topics/async.txt index 944752f3a4b..e27e3e06b6e 100644 --- a/docs/topics/async.txt +++ b/docs/topics/async.txt @@ -111,13 +111,11 @@ For example:: @never_cache - def my_sync_view(request): - ... + def my_sync_view(request): ... @never_cache - async def my_async_view(request): - ... + async def my_async_view(request): ... Queries & the ORM ----------------- @@ -298,16 +296,14 @@ as either a direct wrapper or a decorator:: from asgiref.sync import async_to_sync - async def get_data(): - ... + async def get_data(): ... sync_get_data = async_to_sync(get_data) @async_to_sync - async def get_other_data(): - ... + async def get_other_data(): ... The async function is run in the event loop for the current thread, if one is present. If there is no current event loop, a new event loop is spun up @@ -338,8 +334,7 @@ as either a direct wrapper or a decorator:: @sync_to_async - def sync_function(): - ... + def sync_function(): ... Threadlocals and contextvars values are preserved across the boundary in both directions. diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt index 4aee26d9cae..045710b4204 100644 --- a/docs/topics/auth/default.txt +++ b/docs/topics/auth/default.txt @@ -553,8 +553,7 @@ The ``login_required`` decorator @login_required - def my_view(request): - ... + def my_view(request): ... :func:`~django.contrib.auth.decorators.login_required` does the following: @@ -575,8 +574,7 @@ The ``login_required`` decorator @login_required(redirect_field_name="my_redirect_field") - def my_view(request): - ... + def my_view(request): ... Note that if you provide a value to ``redirect_field_name``, you will most likely need to customize your login template as well, since the template @@ -590,8 +588,7 @@ The ``login_required`` decorator @login_required(login_url="/accounts/login/") - def my_view(request): - ... + def my_view(request): ... Note that if you don't specify the ``login_url`` parameter, you'll need to ensure that the :setting:`settings.LOGIN_URL ` and your login @@ -688,8 +685,7 @@ email in the desired domain and if not, redirects to the login page:: @user_passes_test(email_check) - def my_view(request): - ... + def my_view(request): ... :func:`~django.contrib.auth.decorators.user_passes_test` takes a required argument: a callable that takes a @@ -716,8 +712,7 @@ email in the desired domain and if not, redirects to the login page:: For example:: @user_passes_test(email_check, login_url="/login/") - def my_view(request): - ... + def my_view(request): ... .. currentmodule:: django.contrib.auth.mixins @@ -761,8 +756,7 @@ email in the desired domain and if not, redirects to the login page:: return self.request.user.username.startswith("django") - class MyView(TestMixin1, TestMixin2, View): - ... + class MyView(TestMixin1, TestMixin2, View): ... If ``TestMixin1`` would call ``super()`` and take that result into account, ``TestMixin1`` wouldn't work standalone anymore. @@ -782,8 +776,7 @@ The ``permission_required`` decorator @permission_required("polls.add_choice") - def my_view(request): - ... + def my_view(request): ... Just like the :meth:`~django.contrib.auth.models.User.has_perm` method, permission names take the form ``"."`` @@ -800,8 +793,7 @@ The ``permission_required`` decorator @permission_required("polls.add_choice", login_url="/loginpage/") - def my_view(request): - ... + def my_view(request): ... As in the :func:`~django.contrib.auth.decorators.login_required` decorator, ``login_url`` defaults to :setting:`settings.LOGIN_URL `. @@ -820,8 +812,7 @@ The ``permission_required`` decorator @login_required @permission_required("polls.add_choice", raise_exception=True) - def my_view(request): - ... + def my_view(request): ... This also avoids a redirect loop when :class:`.LoginView`'s ``redirect_authenticated_user=True`` and the logged-in user doesn't have @@ -1608,7 +1599,7 @@ Helper functions Defaults to :setting:`settings.LOGIN_URL ` if not supplied. * ``redirect_field_name``: The name of a ``GET`` field containing the - URL to redirect to after log out. Overrides ``next`` if the given + URL to redirect to after login. Overrides ``next`` if the given ``GET`` parameter is passed. .. _built-in-auth-forms: diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt index 5935c3e27f4..d2951acfa41 100644 --- a/docs/topics/cache.txt +++ b/docs/topics/cache.txt @@ -608,8 +608,9 @@ entire site. You'll need to add Then, add the following required settings to your Django settings file: * :setting:`CACHE_MIDDLEWARE_ALIAS` -- The cache alias to use for storage. -* :setting:`CACHE_MIDDLEWARE_SECONDS` -- The number of seconds each page should - be cached. +* :setting:`CACHE_MIDDLEWARE_SECONDS` -- The integer number of seconds each + page should be cached. + * :setting:`CACHE_MIDDLEWARE_KEY_PREFIX` -- If the cache is shared across multiple sites using the same Django installation, set this to the name of the site, or some other string that is unique to this Django instance, to @@ -668,8 +669,7 @@ decorator that will automatically cache the view's response for you:: @cache_page(60 * 15) - def my_view(request): - ... + def my_view(request): ... ``cache_page`` takes a single argument: the cache timeout, in seconds. In the above example, the result of the ``my_view()`` view will be cached for 15 @@ -699,8 +699,7 @@ which directs the decorator to use a specific cache (from your want:: @cache_page(60 * 15, cache="special_cache") - def my_view(request): - ... + def my_view(request): ... You can also override the cache prefix on a per-view basis. ``cache_page`` takes an optional keyword argument, ``key_prefix``, @@ -708,8 +707,7 @@ which works in the same way as the :setting:`CACHE_MIDDLEWARE_KEY_PREFIX` setting for the middleware. It can be used like this:: @cache_page(60 * 15, key_prefix="site1") - def my_view(request): - ... + def my_view(request): ... The ``key_prefix`` and ``cache`` arguments may be specified together. The ``key_prefix`` argument and the :setting:`KEY_PREFIX ` @@ -1342,8 +1340,7 @@ To do this in Django, use the convenient @vary_on_headers("User-Agent") - def my_view(request): - ... + def my_view(request): ... In this case, a caching mechanism (such as Django's own cache middleware) will cache a separate version of the page for each unique user-agent. @@ -1357,8 +1354,7 @@ anything that was already in there. You can pass multiple headers to ``vary_on_headers()``:: @vary_on_headers("User-Agent", "Cookie") - def my_view(request): - ... + def my_view(request): ... This tells downstream caches to vary on *both*, which means each combination of user-agent and cookie will get its own cache value. For example, a request with @@ -1371,13 +1367,11 @@ Because varying on cookie is so common, there's a are equivalent:: @vary_on_cookie - def my_view(request): - ... + def my_view(request): ... @vary_on_headers("Cookie") - def my_view(request): - ... + def my_view(request): ... The headers you pass to ``vary_on_headers`` are not case sensitive; ``"User-Agent"`` is the same thing as ``"user-agent"``. @@ -1423,8 +1417,7 @@ decorator. Example:: @cache_control(private=True) - def my_view(request): - ... + def my_view(request): ... This decorator takes care of sending out the appropriate HTTP header behind the scenes. @@ -1463,8 +1456,7 @@ directive:: @cache_control(max_age=3600) - def my_view(request): - ... + def my_view(request): ... (If you *do* use the caching middleware, it already sets the ``max-age`` with the value of the :setting:`CACHE_MIDDLEWARE_SECONDS` setting. In that case, @@ -1494,8 +1486,7 @@ caches. Example:: @never_cache - def myview(request): - ... + def myview(request): ... Order of ``MIDDLEWARE`` ======================= diff --git a/docs/topics/checks.txt b/docs/topics/checks.txt index 9a91ceb4690..3e3bbe19d65 100644 --- a/docs/topics/checks.txt +++ b/docs/topics/checks.txt @@ -113,8 +113,7 @@ You can register "deployment checks" that are only relevant to a production settings file like this:: @register(Tags.security, deploy=True) - def my_check(app_configs, **kwargs): - ... + def my_check(app_configs, **kwargs): ... These checks will only be run if the :option:`check --deploy` option is used. @@ -124,8 +123,7 @@ to ``register``. The code below is equivalent to the code above:: - def my_check(app_configs, **kwargs): - ... + def my_check(app_configs, **kwargs): ... register(my_check, Tags.security, deploy=True) diff --git a/docs/topics/conditional-view-processing.txt b/docs/topics/conditional-view-processing.txt index 2447697de46..dfd36a64ae0 100644 --- a/docs/topics/conditional-view-processing.txt +++ b/docs/topics/conditional-view-processing.txt @@ -72,8 +72,7 @@ Suppose you have this pair of models, representing a small blog system:: from django.db import models - class Blog(models.Model): - ... + class Blog(models.Model): ... class Entry(models.Model): @@ -96,8 +95,7 @@ for your front page view:: @condition(last_modified_func=latest_entry) - def front_page(request, blog_id): - ... + def front_page(request, blog_id): ... .. admonition:: Be careful with the order of decorators @@ -131,13 +129,11 @@ We could write the earlier example, which only uses a last-modified function, using one of these decorators:: @last_modified(latest_entry) - def front_page(request, blog_id): - ... + def front_page(request, blog_id): ... ...or:: - def front_page(request, blog_id): - ... + def front_page(request, blog_id): ... front_page = last_modified(latest_entry)(front_page) @@ -154,8 +150,7 @@ this would lead to incorrect behavior. # Bad code. Don't do this! @etag(etag_func) @last_modified(last_modified_func) - def my_view(request): - ... + def my_view(request): ... # End of bad code. diff --git a/docs/topics/db/fixtures.txt b/docs/topics/db/fixtures.txt index 48c5605ff48..ac5b34dae0d 100644 --- a/docs/topics/db/fixtures.txt +++ b/docs/topics/db/fixtures.txt @@ -161,8 +161,7 @@ You could also write a decorator to encapsulate this logic:: @disable_for_loaddata - def my_handler(**kwargs): - ... + def my_handler(**kwargs): ... Just be aware that this logic will disable the signals whenever fixtures are deserialized, not just during :djadmin:`loaddata`. diff --git a/docs/topics/db/managers.txt b/docs/topics/db/managers.txt index 61de153898b..3a7a635e490 100644 --- a/docs/topics/db/managers.txt +++ b/docs/topics/db/managers.txt @@ -380,8 +380,8 @@ this base class:: class Meta: abstract = True -If you use this directly in a subclass, ``objects`` will be the default -manager if you declare no managers in the base class:: +If you use this directly in a child class, ``objects`` will be the default +manager if you declare no managers in the child class:: class ChildA(AbstractBase): # ... diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt index cc6c1f5298d..b419185bbcf 100644 --- a/docs/topics/db/models.txt +++ b/docs/topics/db/models.txt @@ -157,9 +157,12 @@ ones: `, the field will be required. :attr:`~Field.choices` - A :term:`sequence` of 2-tuples to use as choices for this field. If this - is given, the default form widget will be a select box instead of the - standard text field and will limit choices to the choices given. + A :term:`sequence` of 2-value tuples, a :term:`mapping`, an + :ref:`enumeration type `, or a callable (that + expects no arguments and returns any of the previous formats), to use as + choices for this field. If this is given, the default form widget will be a + select box instead of the standard text field and will limit choices to the + choices given. A choices list looks like this:: @@ -216,6 +219,10 @@ ones: Further examples are available in the :ref:`model field reference `. + .. versionchanged:: 5.0 + + Support for mappings and callables was added. + :attr:`~Field.default` The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is diff --git a/docs/topics/db/multi-db.txt b/docs/topics/db/multi-db.txt index 8da71df2500..be7e9953fa8 100644 --- a/docs/topics/db/multi-db.txt +++ b/docs/topics/db/multi-db.txt @@ -740,14 +740,14 @@ primary key of the related object is valid. If the primary key is stored on a separate database, it's not possible to easily evaluate the validity of a primary key. -If you're using Postgres, Oracle, or MySQL with InnoDB, this is +If you're using Postgres, SQLite, Oracle, or MySQL with InnoDB, this is enforced at the database integrity level -- database level key constraints prevent the creation of relations that can't be validated. -However, if you're using SQLite or MySQL with MyISAM tables, there is -no enforced referential integrity; as a result, you may be able to -'fake' cross database foreign keys. However, this configuration is not -officially supported by Django. +However, if you're using MySQL with MyISAM tables, there is no enforced +referential integrity; as a result, you may be able to 'fake' cross database +foreign keys. However, this configuration is not officially supported by +Django. .. _contrib_app_multiple_databases: diff --git a/docs/topics/db/transactions.txt b/docs/topics/db/transactions.txt index 40d40bc7d02..e012d73af48 100644 --- a/docs/topics/db/transactions.txt +++ b/docs/topics/db/transactions.txt @@ -311,8 +311,7 @@ Pass a function, or any callable, to :func:`on_commit`:: from django.db import transaction - def send_welcome_email(): - ... + def send_welcome_email(): ... transaction.on_commit(send_welcome_email) diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt index fbd5695c17d..3727c4f6f52 100644 --- a/docs/topics/forms/modelforms.txt +++ b/docs/topics/forms/modelforms.txt @@ -708,8 +708,7 @@ using the previous ``ArticleForm`` class: .. code-block:: pycon >>> class EnhancedArticleForm(ArticleForm): - ... def clean_pub_date(self): - ... ... + ... def clean_pub_date(self): ... ... This creates a form that behaves identically to ``ArticleForm``, except there's diff --git a/docs/topics/http/file-uploads.txt b/docs/topics/http/file-uploads.txt index cb0fb5b7fbd..3a1c96846c2 100644 --- a/docs/topics/http/file-uploads.txt +++ b/docs/topics/http/file-uploads.txt @@ -346,7 +346,8 @@ list:: @csrf_protect def _upload_file_view(request): - ... # Process request + # Process request + ... If you are using a class-based view, you will need to use :func:`~django.views.decorators.csrf.csrf_exempt` on its @@ -367,4 +368,5 @@ list:: @method_decorator(csrf_protect) def post(self, request, *args, **kwargs): - ... # Process request + # Process request + ... diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt index b7cd7043c2b..74f6fddad6d 100644 --- a/docs/topics/migrations.txt +++ b/docs/topics/migrations.txt @@ -77,16 +77,17 @@ meaning that if a migration fails to apply you will have to manually unpick the changes in order to try again (it's impossible to roll back to an earlier point). -In addition, MySQL will fully rewrite tables for almost every schema operation -and generally takes a time proportional to the number of rows in the table to -add or remove columns. On slower hardware this can be worse than a minute per -million rows - adding a few columns to a table with just a few million rows -could lock your site up for over ten minutes. - -Finally, MySQL has relatively small limits on name lengths for columns, tables -and indexes, as well as a limit on the combined size of all columns an index -covers. This means that indexes that are possible on other backends will -fail to be created under MySQL. +MySQL 8.0 introduced significant performance enhancements for +`DDL operations`_, making them more efficient and reducing the need for full +table rebuilds. However, it cannot guarantee a complete absence of locks or +interruptions. In situations where locks are still necessary, the duration of +these operations will be proportionate to the number of rows involved. + +Finally, MySQL has a relatively small limit on the combined size of all columns +an index covers. This means that indexes that are possible on other backends +will fail to be created under MySQL. + +.. _DDL operations: https://dev.mysql.com/doc/refman/en/innodb-online-ddl-operations.html SQLite ------ diff --git a/docs/topics/settings.txt b/docs/topics/settings.txt index dc6cd945b39..553f788e61e 100644 --- a/docs/topics/settings.txt +++ b/docs/topics/settings.txt @@ -44,9 +44,8 @@ by using an environment variable, :envvar:`DJANGO_SETTINGS_MODULE`. The value of :envvar:`DJANGO_SETTINGS_MODULE` should be in Python path syntax, e.g. ``mysite.settings``. Note that the settings module should be on the -Python `import search path`_. +Python :py:data:`sys.path`. -.. _import search path: https://diveinto.org/python3/your-first-python-program.html#importsearchpath The ``django-admin`` utility ---------------------------- diff --git a/docs/topics/signals.txt b/docs/topics/signals.txt index a4d973ebb42..6a577dd8ad1 100644 --- a/docs/topics/signals.txt +++ b/docs/topics/signals.txt @@ -200,8 +200,7 @@ signals sent by some model:: @receiver(pre_save, sender=MyModel) - def my_handler(sender, **kwargs): - ... + def my_handler(sender, **kwargs): ... The ``my_handler`` function will only be called when an instance of ``MyModel`` is saved. diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt index a415097c560..ae5b7588126 100644 --- a/docs/topics/testing/tools.txt +++ b/docs/topics/testing/tools.txt @@ -1352,8 +1352,7 @@ For example:: class OtherDBTests(TestCase): databases = {"other"} - def test_other_db_query(self): - ... + def test_other_db_query(self): ... This test will only allow queries against the ``other`` database. Just like for :attr:`SimpleTestCase.databases` and :attr:`TransactionTestCase.databases`, the @@ -1954,22 +1953,18 @@ you might label fast or slow tests:: class SampleTestCase(TestCase): @tag("fast") - def test_fast(self): - ... + def test_fast(self): ... @tag("slow") - def test_slow(self): - ... + def test_slow(self): ... @tag("slow", "core") - def test_slow_but_core(self): - ... + def test_slow_but_core(self): ... You can also tag a test case class:: @tag("slow", "core") - class SampleTestCase(TestCase): - ... + class SampleTestCase(TestCase): ... Subclasses inherit tags from superclasses, and methods inherit tags from their class. Given:: @@ -1977,8 +1972,7 @@ class. Given:: @tag("foo") class SampleTestCaseChild(SampleTestCase): @tag("bar") - def test(self): - ... + def test(self): ... ``SampleTestCaseChild.test`` will be labeled with ``'slow'``, ``'core'``, ``'bar'``, and ``'foo'``. @@ -2078,8 +2072,7 @@ creates. class MyTests(TestCase): @mock.patch(...) @async_to_sync - async def test_my_thing(self): - ... + async def test_my_thing(self): ... .. _topics-testing-email: @@ -2160,8 +2153,8 @@ redirected into a ``StringIO`` instance:: class ClosepollTest(TestCase): def test_command_output(self): out = StringIO() - call_command("closepoll", stdout=out) - self.assertIn("Expected output", out.getvalue()) + call_command("closepoll", poll_ids=[1], stdout=out) + self.assertIn('Successfully closed poll "1"', out.getvalue()) .. _skipping-tests: diff --git a/package.json b/package.json index 510d50ad5b1..02589973403 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,11 @@ "npm": ">=1.3.0" }, "devDependencies": { - "eslint": "^8.49.0", - "puppeteer": "^21.1.1", + "eslint": "^8.56.0", + "puppeteer": "^21.7.0", "grunt": "^1.6.1", "grunt-cli": "^1.4.3", - "grunt-contrib-qunit": "^7.0.0", - "qunit": "^2.19.4" + "grunt-contrib-qunit": "^8.0.1", + "qunit": "^2.20.0" } } diff --git a/setup.cfg b/setup.cfg index b93d4250c03..057319c6204 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,7 +38,7 @@ packages = find: include_package_data = true zip_safe = false install_requires = - asgiref >= 3.7.0 + asgiref >= 3.7.0, < 4 sqlparse >= 0.3.1 tzdata; sys_platform == 'win32' diff --git a/tests/admin_changelist/test_date_hierarchy.py b/tests/admin_changelist/test_date_hierarchy.py index 03afaa33d91..94a6a8eb6c6 100644 --- a/tests/admin_changelist/test_date_hierarchy.py +++ b/tests/admin_changelist/test_date_hierarchy.py @@ -90,7 +90,8 @@ def test_invalid_params(self): {"year": 2017, "month": 12, "day": 0}, ) for invalid_query in tests: - with self.subTest(query=invalid_query), self.assertRaises( - IncorrectLookupParameters + with ( + self.subTest(query=invalid_query), + self.assertRaises(IncorrectLookupParameters), ): self.assertDateParams(invalid_query, None, None) diff --git a/tests/admin_inlines/models.py b/tests/admin_inlines/models.py index a8d2ee02e13..eca5bae422c 100644 --- a/tests/admin_inlines/models.py +++ b/tests/admin_inlines/models.py @@ -1,6 +1,7 @@ """ Testing of admin inline formsets. """ + import random from django.contrib.contenttypes.fields import GenericForeignKey diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index 7f39d7fcfc8..50e8d4a3b1e 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -3,6 +3,7 @@ advertised - especially with regards to the handling of the DJANGO_SETTINGS_MODULE and default settings.py files. """ + import os import re import shutil @@ -757,7 +758,9 @@ def test_startapp_unicode_name(self): with open(os.path.join(app_path, "apps.py"), encoding="utf8") as f: content = f.read() self.assertIn("class こんにちはConfig(AppConfig)", content) - self.assertIn('name = "こんにちは"' if HAS_BLACK else "name = 'こんにちは'", content) + self.assertIn( + 'name = "こんにちは"' if HAS_BLACK else "name = 'こんにちは'", content + ) def test_builtin_command(self): """ diff --git a/tests/admin_views/custom_has_permission_admin.py b/tests/admin_views/custom_has_permission_admin.py index 6dc2011b24d..17b6498aab8 100644 --- a/tests/admin_views/custom_has_permission_admin.py +++ b/tests/admin_views/custom_has_permission_admin.py @@ -1,6 +1,7 @@ """ A custom AdminSite for AdminViewPermissionsTest.test_login_has_permission(). """ + from django.contrib import admin from django.contrib.auth import get_permission_codename from django.contrib.auth.forms import AuthenticationForm diff --git a/tests/admin_views/customadmin.py b/tests/admin_views/customadmin.py index e3429ec4bc4..4b30c5c30fd 100644 --- a/tests/admin_views/customadmin.py +++ b/tests/admin_views/customadmin.py @@ -1,6 +1,7 @@ """ A second, custom AdminSite -- see tests.CustomAdminSiteTests. """ + from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py index bfb3919b237..9199bf3eba2 100644 --- a/tests/aggregation_regress/tests.py +++ b/tests/aggregation_regress/tests.py @@ -1564,8 +1564,9 @@ def test_aggregate_unmanaged_model_as_tables(self): "django.db.connection.features.allows_group_by_selected_pks_on_model", return_value=True, ): - with mock.patch.object(Book._meta, "managed", False), mock.patch.object( - Author._meta, "managed", False + with ( + mock.patch.object(Book._meta, "managed", False), + mock.patch.object(Author._meta, "managed", False), ): _, _, grouping = qs.query.get_compiler(using="default").pre_sql_setup() self.assertEqual(len(grouping), 2) diff --git a/tests/asgi/tests.py b/tests/asgi/tests.py index ced24c658e8..bbb274d9ed7 100644 --- a/tests/asgi/tests.py +++ b/tests/asgi/tests.py @@ -1,12 +1,15 @@ import asyncio import sys import threading +import time from pathlib import Path +from asgiref.sync import sync_to_async from asgiref.testing import ApplicationCommunicator from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler from django.core.asgi import get_asgi_application +from django.core.exceptions import RequestDataTooBig from django.core.handlers.asgi import ASGIHandler, ASGIRequest from django.core.signals import request_finished, request_started from django.db import close_old_connections @@ -20,12 +23,24 @@ ) from django.urls import path from django.utils.http import http_date +from django.views.decorators.csrf import csrf_exempt from .urls import sync_waiter, test_filename TEST_STATIC_ROOT = Path(__file__).parent / "project" / "static" +class SignalHandler: + """Helper class to track threads and kwargs when signals are dispatched.""" + + def __init__(self): + super().__init__() + self.calls = [] + + def __call__(self, signal, **kwargs): + self.calls.append({"thread": threading.current_thread(), "kwargs": kwargs}) + + @override_settings(ROOT_URLCONF="asgi.urls") class ASGITest(SimpleTestCase): async_request_factory = AsyncRequestFactory() @@ -196,6 +211,96 @@ async def test_post_body(self): self.assertEqual(response_body["type"], "http.response.body") self.assertEqual(response_body["body"], b"Echo!") + async def test_create_request_error(self): + # Track request_finished signal. + signal_handler = SignalHandler() + request_finished.connect(signal_handler) + self.addCleanup(request_finished.disconnect, signal_handler) + + # Request class that always fails creation with RequestDataTooBig. + class TestASGIRequest(ASGIRequest): + + def __init__(self, scope, body_file): + super().__init__(scope, body_file) + raise RequestDataTooBig() + + # Handler to use the custom request class. + class TestASGIHandler(ASGIHandler): + request_class = TestASGIRequest + + application = TestASGIHandler() + scope = self.async_request_factory._base_scope(path="/not-important/") + communicator = ApplicationCommunicator(application, scope) + + # Initiate request. + await communicator.send_input({"type": "http.request"}) + # Give response.close() time to finish. + await communicator.wait() + + self.assertEqual(len(signal_handler.calls), 1) + self.assertNotEqual( + signal_handler.calls[0]["thread"], threading.current_thread() + ) + + async def test_cancel_post_request_with_sync_processing(self): + """ + The request.body object should be available and readable in view + code, even if the ASGIHandler cancels processing part way through. + """ + loop = asyncio.get_event_loop() + # Events to monitor the view processing from the parent test code. + view_started_event = asyncio.Event() + view_finished_event = asyncio.Event() + # Record received request body or exceptions raised in the test view + outcome = [] + + # This view will run in a new thread because it is wrapped in + # sync_to_async. The view consumes the POST body data after a short + # delay. The test will cancel the request using http.disconnect during + # the delay, but because this is a sync view the code runs to + # completion. There should be no exceptions raised inside the view + # code. + @csrf_exempt + @sync_to_async + def post_view(request): + try: + loop.call_soon_threadsafe(view_started_event.set) + time.sleep(0.1) + # Do something to read request.body after pause + outcome.append({"request_body": request.body}) + return HttpResponse("ok") + except Exception as e: + outcome.append({"exception": e}) + finally: + loop.call_soon_threadsafe(view_finished_event.set) + + # Request class to use the view. + class TestASGIRequest(ASGIRequest): + urlconf = (path("post/", post_view),) + + # Handler to use request class. + class TestASGIHandler(ASGIHandler): + request_class = TestASGIRequest + + application = TestASGIHandler() + scope = self.async_request_factory._base_scope( + method="POST", + path="/post/", + ) + communicator = ApplicationCommunicator(application, scope) + + await communicator.send_input({"type": "http.request", "body": b"Body data!"}) + + # Wait until the view code has started, then send http.disconnect. + await view_started_event.wait() + await communicator.send_input({"type": "http.disconnect"}) + # Wait until view code has finished. + await view_finished_event.wait() + with self.assertRaises(asyncio.TimeoutError): + await communicator.receive_output() + + self.assertEqual(outcome, [{"request_body": b"Body data!"}]) + async def test_untouched_request_body_gets_closed(self): application = get_asgi_application() scope = self.async_request_factory._base_scope(method="POST", path="/post/") @@ -312,17 +417,12 @@ async def test_non_unicode_query_string(self): self.assertEqual(response_body["body"], b"") async def test_request_lifecycle_signals_dispatched_with_thread_sensitive(self): - class SignalHandler: - """Track threads handler is dispatched on.""" - - threads = [] - - def __call__(self, **kwargs): - self.threads.append(threading.current_thread()) - + # Track request_started and request_finished signals. signal_handler = SignalHandler() request_started.connect(signal_handler) + self.addCleanup(request_started.disconnect, signal_handler) request_finished.connect(signal_handler) + self.addCleanup(request_finished.disconnect, signal_handler) # Perform a basic request. application = get_asgi_application() @@ -339,10 +439,11 @@ def __call__(self, **kwargs): await communicator.wait() # AsyncToSync should have executed the signals in the same thread. - request_started_thread, request_finished_thread = signal_handler.threads - self.assertEqual(request_started_thread, request_finished_thread) - request_started.disconnect(signal_handler) - request_finished.disconnect(signal_handler) + self.assertEqual(len(signal_handler.calls), 2) + request_started_call, request_finished_call = signal_handler.calls + self.assertEqual( + request_started_call["thread"], request_finished_call["thread"] + ) async def test_concurrent_async_uses_multiple_thread_pools(self): sync_waiter.active_threads.clear() @@ -378,6 +479,10 @@ async def test_concurrent_async_uses_multiple_thread_pools(self): async def test_asyncio_cancel_error(self): # Flag to check if the view was cancelled. view_did_cancel = False + # Track request_finished signal. + signal_handler = SignalHandler() + request_finished.connect(signal_handler) + self.addCleanup(request_finished.disconnect, signal_handler) # A view that will listen for the cancelled error. async def view(request): @@ -412,6 +517,13 @@ class TestASGIHandler(ASGIHandler): # Give response.close() time to finish. await communicator.wait() self.assertIs(view_did_cancel, False) + # Exactly one call to request_finished handler. + self.assertEqual(len(signal_handler.calls), 1) + handler_call = signal_handler.calls.pop() + # It was NOT on the async thread. + self.assertNotEqual(handler_call["thread"], threading.current_thread()) + # The signal sender is the handler class. + self.assertEqual(handler_call["kwargs"], {"sender": TestASGIHandler}) # Request cycle with a disconnect before the view can respond. application = TestASGIHandler() @@ -427,11 +539,22 @@ class TestASGIHandler(ASGIHandler): await communicator.receive_output() await communicator.wait() self.assertIs(view_did_cancel, True) + # Exactly one call to request_finished handler. + self.assertEqual(len(signal_handler.calls), 1) + handler_call = signal_handler.calls.pop() + # It was NOT on the async thread. + self.assertNotEqual(handler_call["thread"], threading.current_thread()) + # The signal sender is the handler class. + self.assertEqual(handler_call["kwargs"], {"sender": TestASGIHandler}) async def test_asyncio_streaming_cancel_error(self): # Similar to test_asyncio_cancel_error(), but during a streaming # response. view_did_cancel = False + # Track request_finished signals. + signal_handler = SignalHandler() + request_finished.connect(signal_handler) + self.addCleanup(request_finished.disconnect, signal_handler) async def streaming_response(): nonlocal view_did_cancel @@ -466,6 +589,13 @@ class TestASGIHandler(ASGIHandler): self.assertEqual(response_body["body"], b"Hello World!") await communicator.wait() self.assertIs(view_did_cancel, False) + # Exactly one call to request_finished handler. + self.assertEqual(len(signal_handler.calls), 1) + handler_call = signal_handler.calls.pop() + # It was NOT on the async thread. + self.assertNotEqual(handler_call["thread"], threading.current_thread()) + # The signal sender is the handler class. + self.assertEqual(handler_call["kwargs"], {"sender": TestASGIHandler}) # Request cycle with a disconnect. application = TestASGIHandler() @@ -484,6 +614,13 @@ class TestASGIHandler(ASGIHandler): await communicator.receive_output() await communicator.wait() self.assertIs(view_did_cancel, True) + # Exactly one call to request_finished handler. + self.assertEqual(len(signal_handler.calls), 1) + handler_call = signal_handler.calls.pop() + # It was NOT on the async thread. + self.assertNotEqual(handler_call["thread"], threading.current_thread()) + # The signal sender is the handler class. + self.assertEqual(handler_call["kwargs"], {"sender": TestASGIHandler}) async def test_streaming(self): scope = self.async_request_factory._base_scope( diff --git a/tests/auth_tests/models/custom_permissions.py b/tests/auth_tests/models/custom_permissions.py index 52d28bd2762..385de4e8461 100644 --- a/tests/auth_tests/models/custom_permissions.py +++ b/tests/auth_tests/models/custom_permissions.py @@ -3,6 +3,7 @@ Django permissions model. This allows us to check that the PermissionsMixin includes everything that is needed to interact with the ModelBackend. """ + from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.db import models diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py index 81c56a428ea..4583c1f344a 100644 --- a/tests/auth_tests/test_forms.py +++ b/tests/auth_tests/test_forms.py @@ -486,8 +486,9 @@ def signal_handler(**kwargs): user_login_failed.disconnect(signal_handler) def test_inactive_user_i18n(self): - with self.settings(USE_I18N=True), translation.override( - "pt-br", deactivate=True + with ( + self.settings(USE_I18N=True), + translation.override("pt-br", deactivate=True), ): # The user is inactive. data = { @@ -906,9 +907,9 @@ def test_bug_14242(self): class MyUserForm(UserChangeForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields[ - "groups" - ].help_text = "These groups give users different permissions" + self.fields["groups"].help_text = ( + "These groups give users different permissions" + ) class Meta(UserChangeForm.Meta): fields = ("groups",) diff --git a/tests/auth_tests/test_hashers.py b/tests/auth_tests/test_hashers.py index e10992b25c6..cf2ebafa15c 100644 --- a/tests/auth_tests/test_hashers.py +++ b/tests/auth_tests/test_hashers.py @@ -327,8 +327,9 @@ def test_bcrypt_harden_runtime(self): with mock.patch.object(hasher, "rounds", 4): encoded = make_password("letmein", hasher="bcrypt") - with mock.patch.object(hasher, "rounds", 6), mock.patch.object( - hasher, "encode", side_effect=hasher.encode + with ( + mock.patch.object(hasher, "rounds", 6), + mock.patch.object(hasher, "encode", side_effect=hasher.encode), ): hasher.harden_runtime("wrong_password", encoded) @@ -502,8 +503,9 @@ def test_pbkdf2_harden_runtime(self): with mock.patch.object(hasher, "iterations", 1): encoded = make_password("letmein") - with mock.patch.object(hasher, "iterations", 6), mock.patch.object( - hasher, "encode", side_effect=hasher.encode + with ( + mock.patch.object(hasher, "iterations", 6), + mock.patch.object(hasher, "encode", side_effect=hasher.encode), ): hasher.harden_runtime("wrong_password", encoded) @@ -551,8 +553,9 @@ def test_check_password_calls_harden_runtime(self): hasher = get_hasher("default") encoded = make_password("letmein") - with mock.patch.object(hasher, "harden_runtime"), mock.patch.object( - hasher, "must_update", return_value=True + with ( + mock.patch.object(hasher, "harden_runtime"), + mock.patch.object(hasher, "must_update", return_value=True), ): # Correct password supplied, no hardening needed check_password("letmein", encoded) diff --git a/tests/auth_tests/test_views.py b/tests/auth_tests/test_views.py index d15a166c987..0897046c1f5 100644 --- a/tests/auth_tests/test_views.py +++ b/tests/auth_tests/test_views.py @@ -818,9 +818,9 @@ def get_response(request): # Use POST request to log in SessionMiddleware(get_response).process_request(req) CsrfViewMiddleware(get_response).process_view(req, LoginView.as_view(), (), {}) - req.META[ - "SERVER_NAME" - ] = "testserver" # Required to have redirect work in login view + req.META["SERVER_NAME"] = ( + "testserver" # Required to have redirect work in login view + ) req.META["SERVER_PORT"] = 80 resp = CsrfViewMiddleware(LoginView.as_view())(req) csrf_cookie = resp.cookies.get(settings.CSRF_COOKIE_NAME, None) diff --git a/tests/backends/base/test_base.py b/tests/backends/base/test_base.py index ada2cc33c90..3a0f7f1f1cb 100644 --- a/tests/backends/base/test_base.py +++ b/tests/backends/base/test_base.py @@ -168,8 +168,9 @@ def test_database_queried(self): def test_nested_wrapper_invoked(self): outer_wrapper = self.mock_wrapper() inner_wrapper = self.mock_wrapper() - with connection.execute_wrapper(outer_wrapper), connection.execute_wrapper( - inner_wrapper + with ( + connection.execute_wrapper(outer_wrapper), + connection.execute_wrapper(inner_wrapper), ): self.call_execute(connection) self.assertEqual(inner_wrapper.call_count, 1) @@ -182,8 +183,10 @@ def blocker(*args): wrapper = self.mock_wrapper() c = connection # This alias shortens the next line. - with c.execute_wrapper(wrapper), c.execute_wrapper(blocker), c.execute_wrapper( - wrapper + with ( + c.execute_wrapper(wrapper), + c.execute_wrapper(blocker), + c.execute_wrapper(wrapper), ): with c.cursor() as cursor: cursor.execute("The database never sees this") diff --git a/tests/backends/test_utils.py b/tests/backends/test_utils.py index 03d4b036fdf..704498836e4 100644 --- a/tests/backends/test_utils.py +++ b/tests/backends/test_utils.py @@ -1,4 +1,5 @@ """Tests for django.db.backends.utils""" + from decimal import Decimal, Rounded from django.db import NotSupportedError, connection diff --git a/tests/backends/tests.py b/tests/backends/tests.py index 5c562682f0a..08a21d8dedb 100644 --- a/tests/backends/tests.py +++ b/tests/backends/tests.py @@ -1,4 +1,5 @@ """Tests related to django.db.backends that haven't been organized.""" + import datetime import threading import unittest diff --git a/tests/bash_completion/tests.py b/tests/bash_completion/tests.py index 856e351dfa1..324e9809375 100644 --- a/tests/bash_completion/tests.py +++ b/tests/bash_completion/tests.py @@ -1,6 +1,7 @@ """ A series of tests to establish that the command-line bash completion works. """ + import os import sys import unittest diff --git a/tests/basic/models.py b/tests/basic/models.py index b71b60a2135..cd896431408 100644 --- a/tests/basic/models.py +++ b/tests/basic/models.py @@ -3,6 +3,7 @@ This is a basic model with only two non-primary-key fields. """ + import uuid from django.db import models diff --git a/tests/check_framework/test_security.py b/tests/check_framework/test_security.py index b1839f48c3d..cb035a90a4b 100644 --- a/tests/check_framework/test_security.py +++ b/tests/check_framework/test_security.py @@ -593,8 +593,9 @@ def test_with_referrer_policy(self): ("strict-origin", "origin"), ) for value in tests: - with self.subTest(value=value), override_settings( - SECURE_REFERRER_POLICY=value + with ( + self.subTest(value=value), + override_settings(SECURE_REFERRER_POLICY=value), ): self.assertEqual(base.check_referrer_policy(None), []) @@ -663,8 +664,11 @@ def test_no_coop(self): def test_with_coop(self): tests = ["same-origin", "same-origin-allow-popups", "unsafe-none"] for value in tests: - with self.subTest(value=value), override_settings( - SECURE_CROSS_ORIGIN_OPENER_POLICY=value, + with ( + self.subTest(value=value), + override_settings( + SECURE_CROSS_ORIGIN_OPENER_POLICY=value, + ), ): self.assertEqual(base.check_cross_origin_opener_policy(None), []) diff --git a/tests/contenttypes_tests/test_management.py b/tests/contenttypes_tests/test_management.py index eb472d80cef..14ff4e59521 100644 --- a/tests/contenttypes_tests/test_management.py +++ b/tests/contenttypes_tests/test_management.py @@ -88,9 +88,10 @@ def test_unavailable_content_type_model(self): def test_contenttypes_removed_in_installed_apps_without_models(self): ContentType.objects.create(app_label="empty_models", model="Fake 1") ContentType.objects.create(app_label="no_models", model="Fake 2") - with mock.patch( - "builtins.input", return_value="yes" - ), captured_stdout() as stdout: + with ( + mock.patch("builtins.input", return_value="yes"), + captured_stdout() as stdout, + ): call_command("remove_stale_contenttypes", verbosity=2) self.assertNotIn( "Deleting stale content type 'empty_models | Fake 1'", @@ -106,9 +107,10 @@ def test_contenttypes_removed_in_installed_apps_without_models(self): def test_contenttypes_removed_for_apps_not_in_installed_apps(self): ContentType.objects.create(app_label="empty_models", model="Fake 1") ContentType.objects.create(app_label="no_models", model="Fake 2") - with mock.patch( - "builtins.input", return_value="yes" - ), captured_stdout() as stdout: + with ( + mock.patch("builtins.input", return_value="yes"), + captured_stdout() as stdout, + ): call_command( "remove_stale_contenttypes", include_stale_apps=True, verbosity=2 ) diff --git a/tests/contenttypes_tests/test_models.py b/tests/contenttypes_tests/test_models.py index 36c14cf56f2..1999364dd50 100644 --- a/tests/contenttypes_tests/test_models.py +++ b/tests/contenttypes_tests/test_models.py @@ -325,8 +325,9 @@ def test_multidb(self): db_for_read(). """ ContentType.objects.clear_cache() - with self.assertNumQueries(0, using="default"), self.assertNumQueries( - 1, using="other" + with ( + self.assertNumQueries(0, using="default"), + self.assertNumQueries(1, using="other"), ): ContentType.objects.get_for_model(Author) diff --git a/tests/contenttypes_tests/test_views.py b/tests/contenttypes_tests/test_views.py index 4d85d15065f..75f39a7babc 100644 --- a/tests/contenttypes_tests/test_views.py +++ b/tests/contenttypes_tests/test_views.py @@ -150,10 +150,8 @@ def test_shortcut_view_with_null_site_fk(self, get_model): """ The shortcut view works if a model's ForeignKey to site is None. """ - get_model.side_effect = ( - lambda *args, **kwargs: MockSite - if args[0] == "sites.Site" - else ModelWithNullFKToSite + get_model.side_effect = lambda *args, **kwargs: ( + MockSite if args[0] == "sites.Site" else ModelWithNullFKToSite ) obj = ModelWithNullFKToSite.objects.create(title="title") @@ -172,10 +170,8 @@ def test_shortcut_view_with_site_m2m(self, get_model): site if it's attached to the object or to the domain of the first site found in the m2m relationship. """ - get_model.side_effect = ( - lambda *args, **kwargs: MockSite - if args[0] == "sites.Site" - else ModelWithM2MToSite + get_model.side_effect = lambda *args, **kwargs: ( + MockSite if args[0] == "sites.Site" else ModelWithM2MToSite ) # get_current_site() will lookup a Site object, so these must match the diff --git a/tests/context_processors/tests.py b/tests/context_processors/tests.py index 23f9d591496..ba92ff8b05e 100644 --- a/tests/context_processors/tests.py +++ b/tests/context_processors/tests.py @@ -1,6 +1,7 @@ """ Tests for Django's bundled context processors. """ + from django.test import SimpleTestCase, TestCase, override_settings diff --git a/tests/custom_lookups/tests.py b/tests/custom_lookups/tests.py index a636977b67e..22f443d100f 100644 --- a/tests/custom_lookups/tests.py +++ b/tests/custom_lookups/tests.py @@ -238,10 +238,11 @@ class LookupTests(TestCase): def test_custom_name_lookup(self): a1 = Author.objects.create(name="a1", birthdate=date(1981, 2, 16)) Author.objects.create(name="a2", birthdate=date(2012, 2, 29)) - with register_lookup(models.DateField, YearTransform), register_lookup( - models.DateField, YearTransform, lookup_name="justtheyear" - ), register_lookup(YearTransform, Exactly), register_lookup( - YearTransform, Exactly, lookup_name="isactually" + with ( + register_lookup(models.DateField, YearTransform), + register_lookup(models.DateField, YearTransform, lookup_name="justtheyear"), + register_lookup(YearTransform, Exactly), + register_lookup(YearTransform, Exactly, lookup_name="isactually"), ): qs1 = Author.objects.filter(birthdate__testyear__exactly=1981) qs2 = Author.objects.filter(birthdate__justtheyear__isactually=1981) diff --git a/tests/db_functions/comparison/test_nullif.py b/tests/db_functions/comparison/test_nullif.py index 9839e6b4c51..cdbc3d69604 100644 --- a/tests/db_functions/comparison/test_nullif.py +++ b/tests/db_functions/comparison/test_nullif.py @@ -23,9 +23,11 @@ def test_basic(self): [ ("smithj",), ( - "" - if connection.features.interprets_empty_strings_as_nulls - else None, + ( + "" + if connection.features.interprets_empty_strings_as_nulls + else None + ), ), ], ) diff --git a/tests/db_functions/datetime/test_extract_trunc.py b/tests/db_functions/datetime/test_extract_trunc.py index 29212b6e244..e576e6e4641 100644 --- a/tests/db_functions/datetime/test_extract_trunc.py +++ b/tests/db_functions/datetime/test_extract_trunc.py @@ -113,9 +113,11 @@ def create_model(self, start_datetime, end_datetime): end_date=end_datetime.date() if end_datetime else None, start_time=start_datetime.time() if start_datetime else None, end_time=end_datetime.time() if end_datetime else None, - duration=(end_datetime - start_datetime) - if start_datetime and end_datetime - else None, + duration=( + (end_datetime - start_datetime) + if start_datetime and end_datetime + else None + ), ) def test_extract_year_exact_lookup(self): diff --git a/tests/db_functions/models.py b/tests/db_functions/models.py index d6a06511bcc..c126f1bae1a 100644 --- a/tests/db_functions/models.py +++ b/tests/db_functions/models.py @@ -1,6 +1,7 @@ """ Tests for built in Function expressions. """ + from django.db import models diff --git a/tests/db_functions/text/test_md5.py b/tests/db_functions/text/test_md5.py index fd0aec58f2d..4fd66f0397e 100644 --- a/tests/db_functions/text/test_md5.py +++ b/tests/db_functions/text/test_md5.py @@ -35,9 +35,11 @@ def test_basic(self): "ca6d48f6772000141e66591aee49d56c", "bf2c13bc1154e3d2e7df848cbc8be73d", "d41d8cd98f00b204e9800998ecf8427e", - "d41d8cd98f00b204e9800998ecf8427e" - if connection.features.interprets_empty_strings_as_nulls - else None, + ( + "d41d8cd98f00b204e9800998ecf8427e" + if connection.features.interprets_empty_strings_as_nulls + else None + ), ], ) diff --git a/tests/db_functions/text/test_sha1.py b/tests/db_functions/text/test_sha1.py index 175c5727ffc..ef846d07aa5 100644 --- a/tests/db_functions/text/test_sha1.py +++ b/tests/db_functions/text/test_sha1.py @@ -35,9 +35,11 @@ def test_basic(self): "0781e0745a2503e6ded05ed5bc554c421d781b0c", "198d15ea139de04060caf95bc3e0ec5883cba881", "da39a3ee5e6b4b0d3255bfef95601890afd80709", - "da39a3ee5e6b4b0d3255bfef95601890afd80709" - if connection.features.interprets_empty_strings_as_nulls - else None, + ( + "da39a3ee5e6b4b0d3255bfef95601890afd80709" + if connection.features.interprets_empty_strings_as_nulls + else None + ), ], ) diff --git a/tests/db_functions/text/test_sha224.py b/tests/db_functions/text/test_sha224.py index a6254f43e3d..60d9e378a69 100644 --- a/tests/db_functions/text/test_sha224.py +++ b/tests/db_functions/text/test_sha224.py @@ -37,9 +37,11 @@ def test_basic(self): "2297904883e78183cb118fc3dc21a610d60daada7b6ebdbc85139f4d", "eba942746e5855121d9d8f79e27dfdebed81adc85b6bf41591203080", "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", - "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" - if connection.features.interprets_empty_strings_as_nulls - else None, + ( + "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" + if connection.features.interprets_empty_strings_as_nulls + else None + ), ], ) diff --git a/tests/db_functions/text/test_sha256.py b/tests/db_functions/text/test_sha256.py index b399dbecd32..0cf72783e7c 100644 --- a/tests/db_functions/text/test_sha256.py +++ b/tests/db_functions/text/test_sha256.py @@ -35,9 +35,11 @@ def test_basic(self): "6e4cce20cd83fc7c202f21a8b2452a68509cf24d1c272a045b5e0cfc43f0d94e", "3ad2039e3ec0c88973ae1c0fce5a3dbafdd5a1627da0a92312c54ebfcf43988e", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - if connection.features.interprets_empty_strings_as_nulls - else None, + ( + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + if connection.features.interprets_empty_strings_as_nulls + else None + ), ], ) diff --git a/tests/db_functions/text/test_sha384.py b/tests/db_functions/text/test_sha384.py index 250cadda4a0..a4d07d32952 100644 --- a/tests/db_functions/text/test_sha384.py +++ b/tests/db_functions/text/test_sha384.py @@ -39,10 +39,12 @@ def test_basic(self): "26676a43c7ba378621175853b0", "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274ede" "bfe76f65fbd51ad2f14898b95b", - "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274ede" - "bfe76f65fbd51ad2f14898b95b" - if connection.features.interprets_empty_strings_as_nulls - else None, + ( + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da27" + "4edebfe76f65fbd51ad2f14898b95b" + if connection.features.interprets_empty_strings_as_nulls + else None + ), ], ) diff --git a/tests/db_functions/text/test_sha512.py b/tests/db_functions/text/test_sha512.py index f5a7ad4ae54..b4c7a4bbd8a 100644 --- a/tests/db_functions/text/test_sha512.py +++ b/tests/db_functions/text/test_sha512.py @@ -39,10 +39,12 @@ def test_basic(self): "172d88798345a3a7666faf5f35a144c60812d3234dcd35f444624f2faee16857", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", - "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" - "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" - if connection.features.interprets_empty_strings_as_nulls - else None, + ( + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" + "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" + if connection.features.interprets_empty_strings_as_nulls + else None + ), ], ) diff --git a/tests/db_utils/tests.py b/tests/db_utils/tests.py index a2d9cc7b5e8..4028a8acdf3 100644 --- a/tests/db_utils/tests.py +++ b/tests/db_utils/tests.py @@ -1,4 +1,5 @@ """Tests for django.db.utils.""" + import unittest from django.core.exceptions import ImproperlyConfigured diff --git a/tests/dbshell/test_sqlite.py b/tests/dbshell/test_sqlite.py index faf9882ad91..e795f7619b5 100644 --- a/tests/dbshell/test_sqlite.py +++ b/tests/dbshell/test_sqlite.py @@ -35,8 +35,11 @@ def test_non_zero_exit_status_when_path_to_db_is_path(self): cmd_args = self.settings_to_cmd_args_env(sqlite_with_path)[0] msg = '"sqlite3 test.db.sqlite3" returned non-zero exit status 1.' - with mock.patch( - "django.db.backends.sqlite3.client.DatabaseClient.runshell", - side_effect=subprocess.CalledProcessError(returncode=1, cmd=cmd_args), - ), self.assertRaisesMessage(CommandError, msg): + with ( + mock.patch( + "django.db.backends.sqlite3.client.DatabaseClient.runshell", + side_effect=subprocess.CalledProcessError(returncode=1, cmd=cmd_args), + ), + self.assertRaisesMessage(CommandError, msg), + ): call_command("dbshell") diff --git a/tests/distinct_on_fields/tests.py b/tests/distinct_on_fields/tests.py index b80878bbf25..93b3f27aec0 100644 --- a/tests/distinct_on_fields/tests.py +++ b/tests/distinct_on_fields/tests.py @@ -76,9 +76,11 @@ def test_basic_distinct_on(self): (StaffTag.objects.distinct("staff", "tag"), [self.st1]), ( Tag.objects.order_by("parent__pk", "pk").distinct("parent"), - [self.t2, self.t4, self.t1] - if connection.features.nulls_order_largest - else [self.t1, self.t2, self.t4], + ( + [self.t2, self.t4, self.t1] + if connection.features.nulls_order_largest + else [self.t1, self.t2, self.t4] + ), ), ( StaffTag.objects.select_related("staff") diff --git a/tests/expressions/models.py b/tests/expressions/models.py index 0a8a0a6584d..0cab2756311 100644 --- a/tests/expressions/models.py +++ b/tests/expressions/models.py @@ -1,6 +1,7 @@ """ Tests for F() query expression syntax. """ + import uuid from django.db import models diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py index 693efc4c62b..833d841361c 100644 --- a/tests/file_uploads/tests.py +++ b/tests/file_uploads/tests.py @@ -451,9 +451,10 @@ def test_filename_overflow(self): def test_file_content(self): file = tempfile.NamedTemporaryFile - with file(suffix=".ctype_extra") as no_content_type, file( - suffix=".ctype_extra" - ) as simple_file: + with ( + file(suffix=".ctype_extra") as no_content_type, + file(suffix=".ctype_extra") as simple_file, + ): no_content_type.write(b"no content") no_content_type.seek(0) @@ -482,9 +483,10 @@ def test_file_content(self): def test_content_type_extra(self): """Uploaded files may have content type parameters available.""" file = tempfile.NamedTemporaryFile - with file(suffix=".ctype_extra") as no_content_type, file( - suffix=".ctype_extra" - ) as simple_file: + with ( + file(suffix=".ctype_extra") as no_content_type, + file(suffix=".ctype_extra") as simple_file, + ): no_content_type.write(b"something") no_content_type.seek(0) diff --git a/tests/file_uploads/uploadhandler.py b/tests/file_uploads/uploadhandler.py index a1e1a5af053..d3c88ac305b 100644 --- a/tests/file_uploads/uploadhandler.py +++ b/tests/file_uploads/uploadhandler.py @@ -1,6 +1,7 @@ """ Upload handlers to test the upload API. """ + import os from tempfile import NamedTemporaryFile diff --git a/tests/files/tests.py b/tests/files/tests.py index 7dc5c04668c..9d3a471cb31 100644 --- a/tests/files/tests.py +++ b/tests/files/tests.py @@ -144,35 +144,40 @@ def test_file_iteration_with_text(self): self.assertEqual(list(f), ["one\n", "two\n", "three"]) def test_readable(self): - with tempfile.TemporaryFile() as temp, File( - temp, name="something.txt" - ) as test_file: + with ( + tempfile.TemporaryFile() as temp, + File(temp, name="something.txt") as test_file, + ): self.assertTrue(test_file.readable()) self.assertFalse(test_file.readable()) def test_writable(self): - with tempfile.TemporaryFile() as temp, File( - temp, name="something.txt" - ) as test_file: + with ( + tempfile.TemporaryFile() as temp, + File(temp, name="something.txt") as test_file, + ): self.assertTrue(test_file.writable()) self.assertFalse(test_file.writable()) - with tempfile.TemporaryFile("rb") as temp, File( - temp, name="something.txt" - ) as test_file: + with ( + tempfile.TemporaryFile("rb") as temp, + File(temp, name="something.txt") as test_file, + ): self.assertFalse(test_file.writable()) def test_seekable(self): - with tempfile.TemporaryFile() as temp, File( - temp, name="something.txt" - ) as test_file: + with ( + tempfile.TemporaryFile() as temp, + File(temp, name="something.txt") as test_file, + ): self.assertTrue(test_file.seekable()) self.assertFalse(test_file.seekable()) def test_io_wrapper(self): content = "vive l'été\n" - with tempfile.TemporaryFile() as temp, File( - temp, name="something.txt" - ) as test_file: + with ( + tempfile.TemporaryFile() as temp, + File(temp, name="something.txt") as test_file, + ): test_file.write(content.encode()) test_file.seek(0) wrapper = TextIOWrapper(test_file, "utf-8", newline="\n") diff --git a/tests/filtered_relation/models.py b/tests/filtered_relation/models.py index d34a86305fc..765d4956e2a 100644 --- a/tests/filtered_relation/models.py +++ b/tests/filtered_relation/models.py @@ -36,6 +36,8 @@ class Book(models.Model): related_query_name="book", ) editor = models.ForeignKey(Editor, models.CASCADE) + number_editor = models.IntegerField(default=-1) + editor_number = models.IntegerField(default=-2) generic_author = GenericRelation(Author) state = models.CharField(max_length=9, choices=STATES, default=AVAILABLE) diff --git a/tests/filtered_relation/tests.py b/tests/filtered_relation/tests.py index 5a21a47f369..82caba86621 100644 --- a/tests/filtered_relation/tests.py +++ b/tests/filtered_relation/tests.py @@ -792,6 +792,52 @@ def test_conditional_expression_with_multiple_fields(self): ).filter(my_books__isnull=True) self.assertSequenceEqual(qs, []) + def test_conditional_expression_rhs_contains_relation_name(self): + qs = Book.objects.annotate( + rel=FilteredRelation( + "editor", + condition=Q(id=1 * F("number_editor")), + ) + ).filter(rel__isnull=True) + self.assertSequenceEqual(qs, []) + + def test_conditional_expression_rhs_startswith_relation_name(self): + qs = Book.objects.annotate( + rel=FilteredRelation( + "editor", + condition=Q(id=1 * F("editor_number")), + ) + ).filter(rel__isnull=True) + self.assertSequenceEqual(qs, []) + + def test_conditional_expression_lhs_startswith_relation_name(self): + qs = Book.objects.annotate( + rel=FilteredRelation( + "editor", + condition=Q(editor_number__gt=1), + ) + ).filter(rel__isnull=True) + self.assertSequenceEqual(qs, []) + + def test_conditional_expression_lhs_contains_relation_name(self): + qs = Book.objects.annotate( + rel=FilteredRelation( + "editor", + condition=Q(number_editor__gt=1), + ) + ).filter(rel__isnull=True) + self.assertSequenceEqual(qs, []) + + def test_conditional_expression_does_not_support_queryset(self): + msg = "Passing a QuerySet within a FilteredRelation is not supported." + with self.assertRaisesMessage(ValueError, msg): + Author.objects.annotate( + poem_book=FilteredRelation( + "book", + condition=Q(book__in=Book.objects.filter(title__istartswith="a")), + ), + ).filter(poem_book__isnull=False) + class FilteredRelationAggregationTests(TestCase): @classmethod diff --git a/tests/fixtures/models.py b/tests/fixtures/models.py index 37b0066d70c..c87e170afc9 100644 --- a/tests/fixtures/models.py +++ b/tests/fixtures/models.py @@ -101,9 +101,15 @@ class Meta: proxy = True +class VisaManager(models.Manager): + def get_queryset(self): + return super().get_queryset().prefetch_related("permissions") + + class Visa(models.Model): person = models.ForeignKey(Person, models.CASCADE) permissions = models.ManyToManyField(Permission, blank=True) + objects = VisaManager() def __str__(self): return "%s %s" % ( diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py index 78141b25b43..bce55bc3554 100644 --- a/tests/fixtures/tests.py +++ b/tests/fixtures/tests.py @@ -830,6 +830,22 @@ def test_dumpdata_proxy_with_concrete(self): ) self.assertEqual(len(warning_list), 0) + def test_dumpdata_objects_with_prefetch_related(self): + management.call_command( + "loaddata", "fixture6.json", "fixture8.json", verbosity=0 + ) + with self.assertNumQueries(5): + self._dumpdata_assert( + ["fixtures.visa"], + '[{"fields": {"permissions": [["add_user", "auth", "user"]],' + '"person": ["Stephane Grappelli"]},' + '"model": "fixtures.visa", "pk": 2},' + '{"fields": {"permissions": [], "person": ["Prince"]},' + '"model": "fixtures.visa", "pk": 3}]', + natural_foreign_keys=True, + primary_keys="2,3", + ) + def test_compress_format_loading(self): # Load fixture 4 (compressed), using format specification management.call_command("loaddata", "fixture4.json", verbosity=0) diff --git a/tests/force_insert_update/models.py b/tests/force_insert_update/models.py index b95b197454d..e6fdfbd827d 100644 --- a/tests/force_insert_update/models.py +++ b/tests/force_insert_update/models.py @@ -2,6 +2,7 @@ Tests for forcing insert and update queries (instead of Django's normal automatic behavior). """ + from django.db import models diff --git a/tests/forms_tests/field_tests/test_decimalfield.py b/tests/forms_tests/field_tests/test_decimalfield.py index 9d26bc88b0c..cb13e5b71b0 100644 --- a/tests/forms_tests/field_tests/test_decimalfield.py +++ b/tests/forms_tests/field_tests/test_decimalfield.py @@ -80,8 +80,9 @@ def test_enter_a_number_error(self): "--0.12", ) for value in values: - with self.subTest(value=value), self.assertRaisesMessage( - ValidationError, "'Enter a number.'" + with ( + self.subTest(value=value), + self.assertRaisesMessage(ValidationError, "'Enter a number.'"), ): f.clean(value) diff --git a/tests/forms_tests/field_tests/test_filefield.py b/tests/forms_tests/field_tests/test_filefield.py index 11388bdc09d..9744981471a 100644 --- a/tests/forms_tests/field_tests/test_filefield.py +++ b/tests/forms_tests/field_tests/test_filefield.py @@ -53,7 +53,8 @@ def test_filefield_1(self): self.assertIsInstance( f.clean( SimpleUploadedFile( - "我隻氣墊船裝滿晒鱔.txt", "मेरी मँडराने वाली नाव सर्पमीनों से भरी ह".encode() + "我隻氣墊船裝滿晒鱔.txt", + "मेरी मँडराने वाली नाव सर्पमीनों से भरी ह".encode(), ) ), SimpleUploadedFile, diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py index 3c260010c25..f80c1dc09e3 100644 --- a/tests/forms_tests/tests/test_formsets.py +++ b/tests/forms_tests/tests/test_formsets.py @@ -217,9 +217,12 @@ def mocked_func(*args, **kwargs): [("Calexico", "100"), ("Any1", "42"), ("Any2", "101")] ) - with mock.patch( - "django.forms.formsets.ManagementForm.is_valid", mocked_is_valid - ), mock.patch("django.forms.forms.BaseForm.full_clean", mocked_full_clean): + with ( + mock.patch( + "django.forms.formsets.ManagementForm.is_valid", mocked_is_valid + ), + mock.patch("django.forms.forms.BaseForm.full_clean", mocked_full_clean), + ): self.assertTrue(formset.is_valid()) self.assertEqual(is_valid_counter.call_count, 1) self.assertEqual(full_clean_counter.call_count, 4) diff --git a/tests/gis_tests/gdal_tests/test_raster.py b/tests/gis_tests/gdal_tests/test_raster.py index 67108cbb329..a5f1edef0bb 100644 --- a/tests/gis_tests/gdal_tests/test_raster.py +++ b/tests/gis_tests/gdal_tests/test_raster.py @@ -102,8 +102,9 @@ def test_geotransform_bad_inputs(self): ] msg = "Geotransform must consist of 6 numeric values." for geotransform in error_geotransforms: - with self.subTest(i=geotransform), self.assertRaisesMessage( - ValueError, msg + with ( + self.subTest(i=geotransform), + self.assertRaisesMessage(ValueError, msg), ): rsmem.geotransform = geotransform diff --git a/tests/gis_tests/geogapp/tests.py b/tests/gis_tests/geogapp/tests.py index 85656089938..cb783b94653 100644 --- a/tests/gis_tests/geogapp/tests.py +++ b/tests/gis_tests/geogapp/tests.py @@ -1,6 +1,7 @@ """ Tests for geography support in PostGIS """ + import os from django.contrib.gis.db import models diff --git a/tests/gis_tests/test_data.py b/tests/gis_tests/test_data.py index 0a949073208..8dd6042175e 100644 --- a/tests/gis_tests/test_data.py +++ b/tests/gis_tests/test_data.py @@ -2,6 +2,7 @@ This module has the mock object definitions used to hold reference geometry for the GEOS and GDAL tests. """ + import json import os diff --git a/tests/handlers/tests.py b/tests/handlers/tests.py index ab3837d25e0..85f873f3da4 100644 --- a/tests/handlers/tests.py +++ b/tests/handlers/tests.py @@ -244,8 +244,9 @@ def test_no_response(self): ("/no_response_cbv/", "handlers.views.NoResponse.__call__"), ) for url, view in tests: - with self.subTest(url=url), self.assertRaisesMessage( - ValueError, msg % view + with ( + self.subTest(url=url), + self.assertRaisesMessage(ValueError, msg % view), ): self.client.get(url) diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py index 0a41ea5ec63..5f3f195c783 100644 --- a/tests/httpwrappers/tests.py +++ b/tests/httpwrappers/tests.py @@ -352,9 +352,9 @@ def test_long_line(self): h.headers["Content-Disposition"] = 'attachment; filename="%s"' % f # This one is triggering https://bugs.python.org/issue20747, that is Python # will itself insert a newline in the header - h.headers[ - "Content-Disposition" - ] = 'attachment; filename="EdelRot_Blu\u0308te (3)-0.JPG"' + h.headers["Content-Disposition"] = ( + 'attachment; filename="EdelRot_Blu\u0308te (3)-0.JPG"' + ) def test_newlines_in_headers(self): # Bug #10188: Do not allow newlines in headers (CR or LF) diff --git a/tests/humanize_tests/tests.py b/tests/humanize_tests/tests.py index cf29f582329..a78bbadafd8 100644 --- a/tests/humanize_tests/tests.py +++ b/tests/humanize_tests/tests.py @@ -116,39 +116,71 @@ def test_i18n_html_ordinal(self): def test_intcomma(self): test_list = ( 100, + -100, 1000, + -1000, 10123, + -10123, 10311, + -10311, 1000000, + -1000000, 1234567.25, + -1234567.25, "100", + "-100", "1000", + "-1000", "10123", + "-10123", "10311", + "-10311", "1000000", + "-1000000", "1234567.1234567", + "-1234567.1234567", Decimal("1234567.1234567"), + Decimal("-1234567.1234567"), None, "1234567", + "-1234567", "1234567.12", + "-1234567.12", + "the quick brown fox jumped over the lazy dog", ) result_list = ( "100", + "-100", "1,000", + "-1,000", "10,123", + "-10,123", "10,311", + "-10,311", "1,000,000", + "-1,000,000", "1,234,567.25", + "-1,234,567.25", "100", + "-100", "1,000", + "-1,000", "10,123", + "-10,123", "10,311", + "-10,311", "1,000,000", + "-1,000,000", "1,234,567.1234567", + "-1,234,567.1234567", "1,234,567.1234567", + "-1,234,567.1234567", None, "1,234,567", + "-1,234,567", "1,234,567.12", + "-1,234,567.12", + "the quick brown fox jumped over the lazy dog", ) with translation.override("en"): self.humanize_tester(test_list, result_list, "intcomma") @@ -156,39 +188,71 @@ def test_intcomma(self): def test_l10n_intcomma(self): test_list = ( 100, + -100, 1000, + -1000, 10123, + -10123, 10311, + -10311, 1000000, + -1000000, 1234567.25, + -1234567.25, "100", + "-100", "1000", + "-1000", "10123", + "-10123", "10311", + "-10311", "1000000", + "-1000000", "1234567.1234567", + "-1234567.1234567", Decimal("1234567.1234567"), + -Decimal("1234567.1234567"), None, "1234567", + "-1234567", "1234567.12", + "-1234567.12", + "the quick brown fox jumped over the lazy dog", ) result_list = ( "100", + "-100", "1,000", + "-1,000", "10,123", + "-10,123", "10,311", + "-10,311", "1,000,000", + "-1,000,000", "1,234,567.25", + "-1,234,567.25", "100", + "-100", "1,000", + "-1,000", "10,123", + "-10,123", "10,311", + "-10,311", "1,000,000", + "-1,000,000", "1,234,567.1234567", + "-1,234,567.1234567", "1,234,567.1234567", + "-1,234,567.1234567", None, "1,234,567", + "-1,234,567", "1,234,567.12", + "-1,234,567.12", + "the quick brown fox jumped over the lazy dog", ) with self.settings(USE_THOUSAND_SEPARATOR=False): with translation.override("en"): diff --git a/tests/invalid_models_tests/test_models.py b/tests/invalid_models_tests/test_models.py index dc52f58c443..f8451ea1e58 100644 --- a/tests/invalid_models_tests/test_models.py +++ b/tests/invalid_models_tests/test_models.py @@ -2027,15 +2027,18 @@ class Meta: self.assertEqual( Model.check(databases=self.databases), - [ - Error( - "'constraints' refers to the nonexistent field 'missing_field'.", - obj=Model, - id="models.E012", - ), - ] - if connection.features.supports_table_check_constraints - else [], + ( + [ + Error( + "'constraints' refers to the nonexistent field " + "'missing_field'.", + obj=Model, + id="models.E012", + ), + ] + if connection.features.supports_table_check_constraints + else [] + ), ) @skipUnlessDBFeature("supports_table_check_constraints") @@ -2381,15 +2384,18 @@ class Meta: self.assertEqual( Model.check(databases=self.databases), - [ - Error( - "'constraints' refers to the nonexistent field 'missing_field'.", - obj=Model, - id="models.E012", - ), - ] - if connection.features.supports_partial_indexes - else [], + ( + [ + Error( + "'constraints' refers to the nonexistent field " + "'missing_field'.", + obj=Model, + id="models.E012", + ), + ] + if connection.features.supports_partial_indexes + else [] + ), ) def test_unique_constraint_condition_pointing_to_joined_fields(self): @@ -2409,15 +2415,17 @@ class Meta: self.assertEqual( Model.check(databases=self.databases), - [ - Error( - "'constraints' refers to the joined field 'parent__age__lt'.", - obj=Model, - id="models.E041", - ) - ] - if connection.features.supports_partial_indexes - else [], + ( + [ + Error( + "'constraints' refers to the joined field 'parent__age__lt'.", + obj=Model, + id="models.E041", + ) + ] + if connection.features.supports_partial_indexes + else [] + ), ) def test_unique_constraint_pointing_to_reverse_o2o(self): @@ -2436,15 +2444,17 @@ class Meta: self.assertEqual( Model.check(databases=self.databases), - [ - Error( - "'constraints' refers to the nonexistent field 'model'.", - obj=Model, - id="models.E012", - ), - ] - if connection.features.supports_partial_indexes - else [], + ( + [ + Error( + "'constraints' refers to the nonexistent field 'model'.", + obj=Model, + id="models.E012", + ), + ] + if connection.features.supports_partial_indexes + else [] + ), ) def test_deferrable_unique_constraint(self): diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py index 8af459ccd7c..a198a13b62b 100644 --- a/tests/lookup/tests.py +++ b/tests/lookup/tests.py @@ -1522,7 +1522,6 @@ def test_lookup_in_order_by(self): qs = Season.objects.order_by(LessThan(F("year"), 1910), F("year")) self.assertSequenceEqual(qs, [self.s1, self.s3, self.s2]) - @skipUnlessDBFeature("supports_boolean_expr_in_select_clause") def test_aggregate_combined_lookup(self): expression = Cast(GreaterThan(F("year"), 1900), models.IntegerField()) qs = Season.objects.aggregate(modern=models.Sum(expression)) diff --git a/tests/m2m_and_m2o/models.py b/tests/m2m_and_m2o/models.py index 6a5b0b29c98..4cbd1eb4e8c 100644 --- a/tests/m2m_and_m2o/models.py +++ b/tests/m2m_and_m2o/models.py @@ -3,6 +3,7 @@ Make sure to set ``related_name`` if you use relationships to the same table. """ + from django.db import models diff --git a/tests/m2m_intermediary/models.py b/tests/m2m_intermediary/models.py index 1333d14b410..f82498651f6 100644 --- a/tests/m2m_intermediary/models.py +++ b/tests/m2m_intermediary/models.py @@ -9,6 +9,7 @@ field, which specifies the ``Reporter``'s position for the given article (e.g. "Staff writer"). """ + from django.db import models diff --git a/tests/mail/tests.py b/tests/mail/tests.py index 848ee32e9f8..8d51c287b32 100644 --- a/tests/mail/tests.py +++ b/tests/mail/tests.py @@ -1394,8 +1394,9 @@ def test_wrong_admins_managers(self): ): msg = "The %s setting must be a list of 2-tuples." % setting for value in tests: - with self.subTest(setting=setting, value=value), self.settings( - **{setting: value} + with ( + self.subTest(setting=setting, value=value), + self.settings(**{setting: value}), ): with self.assertRaisesMessage(ValueError, msg): mail_func("subject", "content") diff --git a/tests/many_to_many/models.py b/tests/many_to_many/models.py index 541928e94d6..42fc4269904 100644 --- a/tests/many_to_many/models.py +++ b/tests/many_to_many/models.py @@ -6,6 +6,7 @@ In this example, an ``Article`` can be published in multiple ``Publication`` objects, and a ``Publication`` has multiple ``Article`` objects. """ + from django.db import models diff --git a/tests/many_to_one/models.py b/tests/many_to_one/models.py index cca7e798179..56e660592ab 100644 --- a/tests/many_to_one/models.py +++ b/tests/many_to_one/models.py @@ -3,6 +3,7 @@ To define a many-to-one relationship, use ``ForeignKey()``. """ + from django.db import models diff --git a/tests/middleware/test_security.py b/tests/middleware/test_security.py index dd220b8f4c3..339b9181c37 100644 --- a/tests/middleware/test_security.py +++ b/tests/middleware/test_security.py @@ -248,8 +248,9 @@ def test_referrer_policy_on(self): (("strict-origin", "origin"), "strict-origin,origin"), ) for value, expected in tests: - with self.subTest(value=value), override_settings( - SECURE_REFERRER_POLICY=value + with ( + self.subTest(value=value), + override_settings(SECURE_REFERRER_POLICY=value), ): self.assertEqual( self.process_response().headers["Referrer-Policy"], @@ -287,8 +288,11 @@ def test_coop_on(self): """ tests = ["same-origin", "same-origin-allow-popups", "unsafe-none"] for value in tests: - with self.subTest(value=value), override_settings( - SECURE_CROSS_ORIGIN_OPENER_POLICY=value, + with ( + self.subTest(value=value), + override_settings( + SECURE_CROSS_ORIGIN_OPENER_POLICY=value, + ), ): self.assertEqual( self.process_response().headers["Cross-Origin-Opener-Policy"], diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py index 2153a0bb5a6..4771bbe49a2 100644 --- a/tests/middleware/tests.py +++ b/tests/middleware/tests.py @@ -851,9 +851,9 @@ class GZipMiddlewareTest(SimpleTestCase): def setUp(self): self.req = self.request_factory.get("/") self.req.META["HTTP_ACCEPT_ENCODING"] = "gzip, deflate" - self.req.META[ - "HTTP_USER_AGENT" - ] = "Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1" + self.req.META["HTTP_USER_AGENT"] = ( + "Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1" + ) self.resp = HttpResponse() self.resp.status_code = 200 self.resp.content = self.compressible_string diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 85674e552ad..d0a76e10801 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -1310,7 +1310,7 @@ def test_add_not_null_field_with_db_default(self, mocked_ask_method): changes, "testapp", 0, 0, name="name", preserve_default=True ) self.assertOperationFieldAttributes( - changes, "testapp", 0, 0, db_default=models.Value("Ada Lovelace") + changes, "testapp", 0, 0, db_default="Ada Lovelace" ) @mock.patch( @@ -1516,7 +1516,7 @@ def test_alter_field_to_not_null_with_db_default(self, mocked_ask_method): changes, "testapp", 0, 0, name="name", preserve_default=True ) self.assertOperationFieldAttributes( - changes, "testapp", 0, 0, db_default=models.Value("Ada Lovelace") + changes, "testapp", 0, 0, db_default="Ada Lovelace" ) @mock.patch( diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index a9c1cdf8938..c3830eccdbd 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -3102,9 +3102,11 @@ def test_optimization(self): with open(initial_migration_file) as fp: content = fp.read() self.assertIn( - '("bool", models.BooleanField' - if HAS_BLACK - else "('bool', models.BooleanField", + ( + '("bool", models.BooleanField' + if HAS_BLACK + else "('bool', models.BooleanField" + ), content, ) self.assertEqual( @@ -3131,9 +3133,11 @@ def test_optimization_no_verbosity(self): with open(initial_migration_file) as fp: content = fp.read() self.assertIn( - '("bool", models.BooleanField' - if HAS_BLACK - else "('bool', models.BooleanField", + ( + '("bool", models.BooleanField' + if HAS_BLACK + else "('bool', models.BooleanField" + ), content, ) self.assertEqual(out.getvalue(), "") diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py index 6232b44b986..571cb3e1a26 100644 --- a/tests/migrations/test_executor.py +++ b/tests/migrations/test_executor.py @@ -405,9 +405,9 @@ def test_custom_user(self): migrations_apps = executor.loader.project_state( ("migrations", "0001_initial"), ).apps - global_apps.get_app_config("migrations").models[ - "author" - ] = migrations_apps.get_model("migrations", "author") + global_apps.get_app_config("migrations").models["author"] = ( + migrations_apps.get_model("migrations", "author") + ) try: migration = executor.loader.get_migration("auth", "0001_initial") self.assertIs(executor.detect_soft_applied(None, migration)[0], True) diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 670e4c0d37b..9fb8f0aa35a 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -1,4 +1,5 @@ import math +from decimal import Decimal from django.core.exceptions import FieldDoesNotExist from django.db import IntegrityError, connection, migrations, models, transaction @@ -1573,7 +1574,7 @@ def test_add_field_database_default(self): self.assertEqual(len(new_state.models[app_label, "pony"].fields), 6) field = new_state.models[app_label, "pony"].fields["height"] self.assertEqual(field.default, models.NOT_PROVIDED) - self.assertEqual(field.db_default, Value(4)) + self.assertEqual(field.db_default, 4) project_state.apps.get_model(app_label, "pony").objects.create(weight=4) self.assertColumnNotExists(table_name, "height") # Add field. @@ -1624,7 +1625,7 @@ def test_add_field_database_default_special_char_escaping(self): self.assertEqual(len(new_state.models[app_label, "pony"].fields), 6) field = new_state.models[app_label, "pony"].fields["special_char"] self.assertEqual(field.default, models.NOT_PROVIDED) - self.assertEqual(field.db_default, Value(db_default)) + self.assertEqual(field.db_default, db_default) self.assertColumnNotExists(table_name, "special_char") with connection.schema_editor() as editor: operation.database_forwards( @@ -1692,7 +1693,7 @@ def test_add_field_both_defaults(self): self.assertEqual(len(new_state.models[app_label, "pony"].fields), 6) field = new_state.models[app_label, "pony"].fields["height"] self.assertEqual(field.default, 3) - self.assertEqual(field.db_default, Value(4)) + self.assertEqual(field.db_default, 4) pre_pony_pk = ( project_state.apps.get_model(app_label, "pony").objects.create(weight=4).pk ) @@ -2127,7 +2128,7 @@ def test_alter_field_add_database_default(self): old_weight = project_state.models[app_label, "pony"].fields["weight"] self.assertIs(old_weight.db_default, models.NOT_PROVIDED) new_weight = new_state.models[app_label, "pony"].fields["weight"] - self.assertEqual(new_weight.db_default, Value(4.5)) + self.assertEqual(new_weight.db_default, 4.5) with self.assertRaises(IntegrityError), transaction.atomic(): project_state.apps.get_model(app_label, "pony").objects.create() # Alter field. @@ -2169,7 +2170,7 @@ def test_alter_field_change_default_to_database_default(self): self.assertIs(old_pink.db_default, models.NOT_PROVIDED) new_pink = new_state.models[app_label, "pony"].fields["pink"] self.assertIs(new_pink.default, models.NOT_PROVIDED) - self.assertEqual(new_pink.db_default, Value(4)) + self.assertEqual(new_pink.db_default, 4) pony = project_state.apps.get_model(app_label, "pony").objects.create(weight=1) self.assertEqual(pony.pink, 3) # Alter field. @@ -2199,7 +2200,7 @@ def test_alter_field_change_nullable_to_database_default_not_null(self): old_green = project_state.models[app_label, "pony"].fields["green"] self.assertIs(old_green.db_default, models.NOT_PROVIDED) new_green = new_state.models[app_label, "pony"].fields["green"] - self.assertEqual(new_green.db_default, Value(4)) + self.assertEqual(new_green.db_default, 4) old_pony = project_state.apps.get_model(app_label, "pony").objects.create( weight=1 ) @@ -2219,6 +2220,43 @@ def test_alter_field_change_nullable_to_database_default_not_null(self): pony = project_state.apps.get_model(app_label, "pony").objects.create(weight=1) self.assertIsNone(pony.green) + def test_alter_field_change_nullable_to_decimal_database_default_not_null(self): + app_label = "test_alflcntdddn" + project_state = self.set_up_test_model(app_label) + operation_1 = migrations.AddField( + "Pony", + "height", + models.DecimalField(null=True, max_digits=5, decimal_places=2), + ) + operation_2 = migrations.AlterField( + "Pony", + "height", + models.DecimalField( + max_digits=5, decimal_places=2, db_default=Decimal("12.22") + ), + ) + table_name = f"{app_label}_pony" + self.assertColumnNotExists(table_name, "height") + # Add field. + new_state = project_state.clone() + operation_1.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation_1.database_forwards(app_label, editor, project_state, new_state) + self.assertColumnExists(table_name, "height") + old_pony = new_state.apps.get_model(app_label, "pony").objects.create(weight=1) + self.assertIsNone(old_pony.height) + # Alter field. + project_state, new_state = new_state, new_state.clone() + operation_2.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation_2.database_forwards(app_label, editor, project_state, new_state) + old_pony.refresh_from_db() + self.assertEqual(old_pony.height, Decimal("12.22")) + pony = new_state.apps.get_model(app_label, "pony").objects.create(weight=2) + if not connection.features.can_return_columns_from_insert: + pony.refresh_from_db() + self.assertEqual(pony.height, Decimal("12.22")) + @skipIfDBFeature("interprets_empty_strings_as_nulls") def test_alter_field_change_blank_nullable_database_default_to_not_null(self): app_label = "test_alflcbnddnn" @@ -3569,15 +3607,17 @@ def test_rename_index(self): operation.state_forwards(app_label, new_state) # Rename index. expected_queries = 1 if connection.features.can_rename_index else 2 - with connection.schema_editor() as editor, self.assertNumQueries( - expected_queries + with ( + connection.schema_editor() as editor, + self.assertNumQueries(expected_queries), ): operation.database_forwards(app_label, editor, project_state, new_state) self.assertIndexNameNotExists(table_name, "pony_pink_idx") self.assertIndexNameExists(table_name, "new_pony_test_idx") # Reversal. - with connection.schema_editor() as editor, self.assertNumQueries( - expected_queries + with ( + connection.schema_editor() as editor, + self.assertNumQueries(expected_queries), ): operation.database_backwards(app_label, editor, new_state, project_state) self.assertIndexNameExists(table_name, "pony_pink_idx") @@ -4343,9 +4383,10 @@ def test_add_deferred_unique_constraint(self): ) Pony = new_state.apps.get_model(app_label, "Pony") self.assertEqual(len(Pony._meta.constraints), 1) - with connection.schema_editor() as editor, CaptureQueriesContext( - connection - ) as ctx: + with ( + connection.schema_editor() as editor, + CaptureQueriesContext(connection) as ctx, + ): operation.database_forwards(app_label, editor, project_state, new_state) Pony.objects.create(pink=1, weight=4.0) if connection.features.supports_deferrable_unique_constraints: @@ -4404,9 +4445,10 @@ def test_remove_deferred_unique_constraint(self): ) Pony = new_state.apps.get_model(app_label, "Pony") self.assertEqual(len(Pony._meta.constraints), 0) - with connection.schema_editor() as editor, CaptureQueriesContext( - connection - ) as ctx: + with ( + connection.schema_editor() as editor, + CaptureQueriesContext(connection) as ctx, + ): operation.database_forwards(app_label, editor, project_state, new_state) # Constraint doesn't work. Pony.objects.create(pink=1, weight=4.0) @@ -4467,9 +4509,10 @@ def test_add_covering_unique_constraint(self): ) Pony = new_state.apps.get_model(app_label, "Pony") self.assertEqual(len(Pony._meta.constraints), 1) - with connection.schema_editor() as editor, CaptureQueriesContext( - connection - ) as ctx: + with ( + connection.schema_editor() as editor, + CaptureQueriesContext(connection) as ctx, + ): operation.database_forwards(app_label, editor, project_state, new_state) Pony.objects.create(pink=1, weight=4.0) if connection.features.supports_covering_indexes: @@ -4515,9 +4558,10 @@ def test_remove_covering_unique_constraint(self): ) Pony = new_state.apps.get_model(app_label, "Pony") self.assertEqual(len(Pony._meta.constraints), 0) - with connection.schema_editor() as editor, CaptureQueriesContext( - connection - ) as ctx: + with ( + connection.schema_editor() as editor, + CaptureQueriesContext(connection) as ctx, + ): operation.database_forwards(app_label, editor, project_state, new_state) # Constraint doesn't work. Pony.objects.create(pink=1, weight=4.0) diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py index b4b7b5bd4c5..e34f3c8947a 100644 --- a/tests/model_fields/models.py +++ b/tests/model_fields/models.py @@ -482,6 +482,18 @@ class UUIDGrandchild(UUIDChild): pass +class GeneratedModelFieldWithConverters(models.Model): + field = models.UUIDField() + field_copy = models.GeneratedField( + expression=F("field"), + output_field=models.UUIDField(), + db_persist=True, + ) + + class Meta: + required_db_features = {"supports_stored_generated_columns"} + + class GeneratedModel(models.Model): a = models.IntegerField() b = models.IntegerField() @@ -490,6 +502,7 @@ class GeneratedModel(models.Model): output_field=models.IntegerField(), db_persist=True, ) + fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True, blank=True) class Meta: required_db_features = {"supports_stored_generated_columns"} @@ -503,6 +516,7 @@ class GeneratedModelVirtual(models.Model): output_field=models.IntegerField(), db_persist=False, ) + fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True, blank=True) class Meta: required_db_features = {"supports_virtual_generated_columns"} diff --git a/tests/model_fields/test_generatedfield.py b/tests/model_fields/test_generatedfield.py index 9e5d9d87c36..a636e984fdb 100644 --- a/tests/model_fields/test_generatedfield.py +++ b/tests/model_fields/test_generatedfield.py @@ -1,3 +1,6 @@ +import uuid +from decimal import Decimal + from django.apps import apps from django.db import IntegrityError, connection from django.db.models import ( @@ -13,7 +16,9 @@ from django.test.utils import isolate_apps from .models import ( + Foo, GeneratedModel, + GeneratedModelFieldWithConverters, GeneratedModelNull, GeneratedModelNullVirtual, GeneratedModelOutputFieldDbCollation, @@ -163,6 +168,14 @@ def test_unsaved_error(self): with self.assertRaisesMessage(AttributeError, msg): m.field + def test_full_clean(self): + m = self.base_model(a=1, b=2) + # full_clean() ignores GeneratedFields. + m.full_clean() + m.save() + m = self._refresh_if_needed(m) + self.assertEqual(m.field, 3) + def test_create(self): m = self.base_model.objects.create(a=1, b=2) m = self._refresh_if_needed(m) @@ -184,6 +197,19 @@ def test_save(self): m.refresh_from_db() self.assertEqual(m.field, 8) + def test_save_model_with_foreign_key(self): + fk_object = Foo.objects.create(a="abc", d=Decimal("12.34")) + m = self.base_model(a=1, b=2, fk=fk_object) + m.save() + m = self._refresh_if_needed(m) + self.assertEqual(m.field, 3) + + def test_generated_fields_can_be_deferred(self): + fk_object = Foo.objects.create(a="abc", d=Decimal("12.34")) + m = self.base_model.objects.create(a=1, b=2, fk=fk_object) + m = self.base_model.objects.defer("field").get(id=m.id) + self.assertEqual(m.get_deferred_fields(), {"field"}) + def test_update(self): m = self.base_model.objects.create(a=1, b=2) self.base_model.objects.update(b=3) @@ -266,6 +292,11 @@ class StoredGeneratedFieldTests(GeneratedFieldTestMixin, TestCase): output_field_db_collation_model = GeneratedModelOutputFieldDbCollation params_model = GeneratedModelParams + def test_create_field_with_db_converters(self): + obj = GeneratedModelFieldWithConverters.objects.create(field=uuid.uuid4()) + obj = self._refresh_if_needed(obj) + self.assertEqual(obj.field, obj.field_copy) + @skipUnlessDBFeature("supports_virtual_generated_columns") class VirtualGeneratedFieldTests(GeneratedFieldTestMixin, TestCase): diff --git a/tests/model_inheritance/models.py b/tests/model_inheritance/models.py index 47aae186e03..ffb9f28cfa6 100644 --- a/tests/model_inheritance/models.py +++ b/tests/model_inheritance/models.py @@ -11,6 +11,7 @@ Both styles are demonstrated here. """ + from django.db import models # diff --git a/tests/model_inheritance/tests.py b/tests/model_inheritance/tests.py index 5bf1ef5db54..6b005fcef0e 100644 --- a/tests/model_inheritance/tests.py +++ b/tests/model_inheritance/tests.py @@ -216,9 +216,11 @@ def b(): GrandChild().save() for i, test in enumerate([a, b]): - with self.subTest(i=i), self.assertNumQueries(4), CaptureQueriesContext( - connection - ) as queries: + with ( + self.subTest(i=i), + self.assertNumQueries(4), + CaptureQueriesContext(connection) as queries, + ): test() for query in queries: sql = query["sql"] diff --git a/tests/model_inheritance_regress/tests.py b/tests/model_inheritance_regress/tests.py index 1a9f953d6f1..ba31048ac2f 100644 --- a/tests/model_inheritance_regress/tests.py +++ b/tests/model_inheritance_regress/tests.py @@ -1,6 +1,7 @@ """ Regression tests for Model inheritance behavior. """ + import datetime from operator import attrgetter from unittest import expectedFailure diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py index 2ed27f8a3dd..85c175d5812 100644 --- a/tests/modeladmin/test_checks.py +++ b/tests/modeladmin/test_checks.py @@ -322,6 +322,24 @@ class TestModelAdmin(ModelAdmin): "admin.E020", ) + @isolate_apps("modeladmin") + def test_invalid_reverse_m2m_field_with_related_name(self): + class Contact(Model): + pass + + class Customer(Model): + contacts = ManyToManyField("Contact", related_name="customers") + + class TestModelAdmin(ModelAdmin): + filter_vertical = ["customers"] + + self.assertIsInvalid( + TestModelAdmin, + Contact, + "The value of 'filter_vertical[0]' must be a many-to-many field.", + "admin.E020", + ) + @isolate_apps("modeladmin") def test_invalid_m2m_field_with_through(self): class Artist(Model): @@ -384,6 +402,24 @@ class TestModelAdmin(ModelAdmin): "admin.E020", ) + @isolate_apps("modeladmin") + def test_invalid_reverse_m2m_field_with_related_name(self): + class Contact(Model): + pass + + class Customer(Model): + contacts = ManyToManyField("Contact", related_name="customers") + + class TestModelAdmin(ModelAdmin): + filter_horizontal = ["customers"] + + self.assertIsInvalid( + TestModelAdmin, + Contact, + "The value of 'filter_horizontal[0]' must be a many-to-many field.", + "admin.E020", + ) + @isolate_apps("modeladmin") def test_invalid_m2m_field_with_through(self): class Artist(Model): diff --git a/tests/modeladmin/tests.py b/tests/modeladmin/tests.py index f2763ecc0fb..dce91b23e41 100644 --- a/tests/modeladmin/tests.py +++ b/tests/modeladmin/tests.py @@ -162,6 +162,34 @@ class EmployeeProfileAdmin(ModelAdmin): True, ) + @isolate_apps("modeladmin") + def test_lookup_allowed_for_local_fk_fields(self): + class Country(models.Model): + pass + + class Place(models.Model): + country = models.ForeignKey(Country, models.CASCADE) + + class PlaceAdmin(ModelAdmin): + pass + + ma = PlaceAdmin(Place, self.site) + self.assertIs(ma.lookup_allowed("country", "1", request), True) + + @isolate_apps("modeladmin") + def test_lookup_allowed_non_autofield_primary_key(self): + class Country(models.Model): + id = models.CharField(max_length=2, primary_key=True) + + class Place(models.Model): + country = models.ForeignKey(Country, models.CASCADE) + + class PlaceAdmin(ModelAdmin): + list_filter = ["country"] + + ma = PlaceAdmin(Place, self.site) + self.assertIs(ma.lookup_allowed("country__id__exact", "DE", request), True) + @isolate_apps("modeladmin") def test_lookup_allowed_foreign_primary(self): class Country(models.Model): diff --git a/tests/null_fk_ordering/models.py b/tests/null_fk_ordering/models.py index adfdbf3bea4..d7b6ad82389 100644 --- a/tests/null_fk_ordering/models.py +++ b/tests/null_fk_ordering/models.py @@ -5,6 +5,7 @@ unexpected results """ + from django.db import models diff --git a/tests/one_to_one/models.py b/tests/one_to_one/models.py index ca459e9edfe..20b2eeec7da 100644 --- a/tests/one_to_one/models.py +++ b/tests/one_to_one/models.py @@ -5,6 +5,7 @@ In this example, a ``Place`` optionally can be a ``Restaurant``. """ + from django.db import models diff --git a/tests/order_with_respect_to/base_tests.py b/tests/order_with_respect_to/base_tests.py index ea548ca076e..5170c6d957e 100644 --- a/tests/order_with_respect_to/base_tests.py +++ b/tests/order_with_respect_to/base_tests.py @@ -2,6 +2,7 @@ The tests are shared with contenttypes_tests and so shouldn't import or reference any models directly. Subclasses should inherit django.test.TestCase. """ + from operator import attrgetter @@ -117,8 +118,11 @@ def db_for_write(self, model, **hints): return "other" with self.settings(DATABASE_ROUTERS=[WriteToOtherRouter()]): - with self.assertNumQueries(0, using="default"), self.assertNumQueries( - 1, - using="other", + with ( + self.assertNumQueries(0, using="default"), + self.assertNumQueries( + 1, + using="other", + ), ): self.q1.set_answer_order([3, 1, 2, 4]) diff --git a/tests/postgres_tests/fields.py b/tests/postgres_tests/fields.py index 1565b5ed439..7c93d2039ed 100644 --- a/tests/postgres_tests/fields.py +++ b/tests/postgres_tests/fields.py @@ -2,6 +2,7 @@ Indirection layer for PostgreSQL-specific fields, so the tests don't fail when run with a backend other than PostgreSQL. """ + import enum from django.db import models diff --git a/tests/postgres_tests/test_constraints.py b/tests/postgres_tests/test_constraints.py index bf478337430..e5a8e9dbe9e 100644 --- a/tests/postgres_tests/test_constraints.py +++ b/tests/postgres_tests/test_constraints.py @@ -300,8 +300,9 @@ def test_invalid_expressions(self): def test_empty_expressions(self): msg = "At least one expression is required to define an exclusion constraint." for empty_expressions in (None, []): - with self.subTest(empty_expressions), self.assertRaisesMessage( - ValueError, msg + with ( + self.subTest(empty_expressions), + self.assertRaisesMessage(ValueError, msg), ): ExclusionConstraint( index_type="GIST", diff --git a/tests/postgres_tests/test_search.py b/tests/postgres_tests/test_search.py index 6f6318899c2..472dca6c7b7 100644 --- a/tests/postgres_tests/test_search.py +++ b/tests/postgres_tests/test_search.py @@ -5,6 +5,7 @@ All text copyright Python (Monty) Pictures. Thanks to sacred-texts.com for the transcript. """ + from django.db.models import F, Value from . import PostgreSQLSimpleTestCase, PostgreSQLTestCase diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py index 08f87d55de1..a418beb5a52 100644 --- a/tests/prefetch_related/tests.py +++ b/tests/prefetch_related/tests.py @@ -1620,8 +1620,9 @@ def test_using_is_honored_custom_qs(self): ) # Explicit using on a different db. - with self.assertNumQueries(1, using="default"), self.assertNumQueries( - 1, using="other" + with ( + self.assertNumQueries(1, using="default"), + self.assertNumQueries(1, using="other"), ): prefetch = Prefetch( "first_time_authors", queryset=Author.objects.using("default") diff --git a/tests/proxy_models/models.py b/tests/proxy_models/models.py index 604136b5ac6..c0277e093fb 100644 --- a/tests/proxy_models/models.py +++ b/tests/proxy_models/models.py @@ -4,6 +4,7 @@ than using a new table of their own. This allows them to act as simple proxies, providing a modified interface to the data from the base class. """ + from django.db import models # A couple of managers for testing managing overriding in proxy model cases. diff --git a/tests/queries/models.py b/tests/queries/models.py index 23c41e33742..9f4cf040b62 100644 --- a/tests/queries/models.py +++ b/tests/queries/models.py @@ -1,6 +1,7 @@ """ Various complex queries that have been problematic in the past. """ + import datetime from django.db import models diff --git a/tests/requests_tests/test_accept_header.py b/tests/requests_tests/test_accept_header.py index c6eed0e4793..5afb9e99932 100644 --- a/tests/requests_tests/test_accept_header.py +++ b/tests/requests_tests/test_accept_header.py @@ -68,9 +68,9 @@ def test_no_headers(self): def test_accept_headers(self): request = HttpRequest() - request.META[ - "HTTP_ACCEPT" - ] = "text/html, application/xhtml+xml,application/xml ;q=0.9,*/*;q=0.8" + request.META["HTTP_ACCEPT"] = ( + "text/html, application/xhtml+xml,application/xml ;q=0.9,*/*;q=0.8" + ) self.assertEqual( [str(accepted_type) for accepted_type in request.accepted_types], [ @@ -94,9 +94,9 @@ def test_request_accepts_none(self): def test_request_accepts_some(self): request = HttpRequest() - request.META[ - "HTTP_ACCEPT" - ] = "text/html,application/xhtml+xml,application/xml;q=0.9" + request.META["HTTP_ACCEPT"] = ( + "text/html,application/xhtml+xml,application/xml;q=0.9" + ) self.assertIs(request.accepts("text/html"), True) self.assertIs(request.accepts("application/xhtml+xml"), True) self.assertIs(request.accepts("application/xml"), True) diff --git a/tests/save_delete_hooks/models.py b/tests/save_delete_hooks/models.py index e7c598aeaed..8b9826eb145 100644 --- a/tests/save_delete_hooks/models.py +++ b/tests/save_delete_hooks/models.py @@ -4,6 +4,7 @@ To execute arbitrary code around ``save()`` and ``delete()``, just subclass the methods. """ + from django.db import models diff --git a/tests/schema/fields.py b/tests/schema/fields.py index 998cb28b8cf..24a26b2c2c0 100644 --- a/tests/schema/fields.py +++ b/tests/schema/fields.py @@ -41,9 +41,11 @@ def __init__( related_name=related_name, related_query_name=related_query_name, limit_choices_to=limit_choices_to, - symmetrical=symmetrical - if symmetrical is not None - else (to == RECURSIVE_RELATIONSHIP_CONSTANT), + symmetrical=( + symmetrical + if symmetrical is not None + else (to == RECURSIVE_RELATIONSHIP_CONSTANT) + ), through=through, through_fields=through_fields, db_constraint=db_constraint, diff --git a/tests/schema/tests.py b/tests/schema/tests.py index 046097366c2..465245e3e7c 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -7,6 +7,7 @@ from django.core.exceptions import FieldError from django.core.management.color import no_style +from django.core.serializers.json import DjangoJSONEncoder from django.db import ( DatabaseError, DataError, @@ -646,9 +647,10 @@ def test_add_field(self): # Add the new field new_field = IntegerField(null=True) new_field.set_attributes_from_name("age") - with CaptureQueriesContext( - connection - ) as ctx, connection.schema_editor() as editor: + with ( + CaptureQueriesContext(connection) as ctx, + connection.schema_editor() as editor, + ): editor.add_field(Author, new_field) drop_default_sql = editor.sql_alter_column_no_default % { "column": editor.quote_name(new_field.name), @@ -852,6 +854,27 @@ class Meta: False, ) + @isolate_apps("schema") + @skipUnlessDBFeature("supports_virtual_generated_columns") + def test_add_generated_boolean_field(self): + class GeneratedBooleanFieldModel(Model): + value = IntegerField(null=True) + has_value = GeneratedField( + expression=Q(value__isnull=False), + output_field=BooleanField(), + db_persist=False, + ) + + class Meta: + app_label = "schema" + + with connection.schema_editor() as editor: + editor.create_model(GeneratedBooleanFieldModel) + obj = GeneratedBooleanFieldModel.objects.create() + self.assertIs(obj.has_value, False) + obj = GeneratedBooleanFieldModel.objects.create(value=1) + self.assertIs(obj.has_value, True) + @isolate_apps("schema") @skipUnlessDBFeature("supports_stored_generated_columns") def test_add_generated_field(self): @@ -2284,6 +2307,56 @@ class Meta: columns = self.column_classes(Author) self.assertEqual(columns["birth_year"][1].default, "1988") + @isolate_apps("schema") + def test_add_text_field_with_db_default(self): + class Author(Model): + description = TextField(db_default="(missing)") + + class Meta: + app_label = "schema" + + with connection.schema_editor() as editor: + editor.create_model(Author) + columns = self.column_classes(Author) + self.assertIn("(missing)", columns["description"][1].default) + + @isolate_apps("schema") + def test_db_default_equivalent_sql_noop(self): + class Author(Model): + name = TextField(db_default=Value("foo")) + + class Meta: + app_label = "schema" + + with connection.schema_editor() as editor: + editor.create_model(Author) + + new_field = TextField(db_default="foo") + new_field.set_attributes_from_name("name") + new_field.model = Author + with connection.schema_editor() as editor, self.assertNumQueries(0): + editor.alter_field(Author, Author._meta.get_field("name"), new_field) + + @isolate_apps("schema") + def test_db_default_output_field_resolving(self): + class Author(Model): + data = JSONField( + encoder=DjangoJSONEncoder, + db_default={ + "epoch": datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc) + }, + ) + + class Meta: + app_label = "schema" + + with connection.schema_editor() as editor: + editor.create_model(Author) + + author = Author.objects.create() + author.refresh_from_db() + self.assertEqual(author.data, {"epoch": "1970-01-01T00:00:00Z"}) + @skipUnlessDBFeature( "supports_column_check_constraints", "can_introspect_check_constraints" ) @@ -2465,9 +2538,10 @@ class Meta: with self.assertRaises(DatabaseError): self.column_classes(new_field.remote_field.through) # Add the field - with CaptureQueriesContext( - connection - ) as ctx, connection.schema_editor() as editor: + with ( + CaptureQueriesContext(connection) as ctx, + connection.schema_editor() as editor, + ): editor.add_field(LocalAuthorWithM2M, new_field) # Table is not rebuilt. self.assertEqual( @@ -2945,9 +3019,11 @@ def test_remove_ignored_unique_constraint_not_create_fk_index(self): ) # Redundant foreign key index is not added. self.assertEqual( - len(old_constraints) - 1 - if connection.features.supports_partial_indexes - else len(old_constraints), + ( + len(old_constraints) - 1 + if connection.features.supports_partial_indexes + else len(old_constraints) + ), len(new_constraints), ) diff --git a/tests/serializers/models/base.py b/tests/serializers/models/base.py index c5a4a0f5802..e4fcee366d5 100644 --- a/tests/serializers/models/base.py +++ b/tests/serializers/models/base.py @@ -4,6 +4,7 @@ ``django.core.serializers`` provides interfaces to converting Django ``QuerySet`` objects to and from "flat" data (i.e. strings). """ + from decimal import Decimal from django.db import models diff --git a/tests/serializers/models/data.py b/tests/serializers/models/data.py index 3d863a3fb2b..a0e8751461a 100644 --- a/tests/serializers/models/data.py +++ b/tests/serializers/models/data.py @@ -4,6 +4,7 @@ NULL values, where allowed. The basic idea is to have a model for each Django data type. """ + import uuid from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation diff --git a/tests/serializers/models/natural.py b/tests/serializers/models/natural.py index 1e439b34ebd..cfc57b11278 100644 --- a/tests/serializers/models/natural.py +++ b/tests/serializers/models/natural.py @@ -1,4 +1,5 @@ """Models for test_natural.py""" + import uuid from django.db import models diff --git a/tests/serializers/test_data.py b/tests/serializers/test_data.py index e1cb776d834..6361dc0c05f 100644 --- a/tests/serializers/test_data.py +++ b/tests/serializers/test_data.py @@ -6,6 +6,7 @@ the serializers. This includes all valid data values, plus forward, backwards and self references. """ + import datetime import decimal import uuid diff --git a/tests/servers/tests.py b/tests/servers/tests.py index ea49c11534f..05898009d53 100644 --- a/tests/servers/tests.py +++ b/tests/servers/tests.py @@ -1,6 +1,7 @@ """ Tests for django.core.servers. """ + import errno import os import socket diff --git a/tests/sessions_tests/models.py b/tests/sessions_tests/models.py index 6eda26f22af..93f80b347d6 100644 --- a/tests/sessions_tests/models.py +++ b/tests/sessions_tests/models.py @@ -3,6 +3,7 @@ real-world applications, it gives you the option of querying the database for all active sessions for a particular account. """ + from django.contrib.sessions.backends.db import SessionStore as DBStore from django.contrib.sessions.base_session import AbstractBaseSession from django.db import models diff --git a/tests/signals/models.py b/tests/signals/models.py index b758244749a..5fb9f9f772c 100644 --- a/tests/signals/models.py +++ b/tests/signals/models.py @@ -1,6 +1,7 @@ """ Testing signals before/after saving and deleting. """ + from django.db import models diff --git a/tests/template_tests/test_parser.py b/tests/template_tests/test_parser.py index e40a5611e21..eb3bb491138 100644 --- a/tests/template_tests/test_parser.py +++ b/tests/template_tests/test_parser.py @@ -2,6 +2,7 @@ Testing some internals of the template processing. These are *not* examples to be copied in user code. """ + from django.template import Library, TemplateSyntaxError from django.template.base import ( FilterExpression, diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py index 402f282588d..bfb0bd98ea9 100644 --- a/tests/test_client/tests.py +++ b/tests/test_client/tests.py @@ -19,6 +19,7 @@ rather than the HTML rendered to the end-user. """ + import copy import itertools import tempfile diff --git a/tests/test_client_regress/tests.py b/tests/test_client_regress/tests.py index 726d1dcf8f1..bd5239ce243 100644 --- a/tests/test_client_regress/tests.py +++ b/tests/test_client_regress/tests.py @@ -1,6 +1,7 @@ """ Regression tests for the Test Client, especially the customized assertions. """ + import itertools import os diff --git a/tests/test_runner/test_discover_runner.py b/tests/test_runner/test_discover_runner.py index 5fc35b7bf21..a845f6dd67d 100644 --- a/tests/test_runner/test_discover_runner.py +++ b/tests/test_runner/test_discover_runner.py @@ -658,9 +658,10 @@ def test_faulthandler_already_enabled(self, mocked_enable): @mock.patch("faulthandler.enable") def test_faulthandler_enabled_fileno(self, mocked_enable): # sys.stderr that is not an actual file. - with mock.patch( - "faulthandler.is_enabled", return_value=False - ), captured_stderr(): + with ( + mock.patch("faulthandler.is_enabled", return_value=False), + captured_stderr(), + ): DiscoverRunner(enable_faulthandler=True) mocked_enable.assert_called() diff --git a/tests/test_runner/tests.py b/tests/test_runner/tests.py index 569fd7e8621..b900ff69ea0 100644 --- a/tests/test_runner/tests.py +++ b/tests/test_runner/tests.py @@ -1,6 +1,7 @@ """ Tests for django test runner """ + import collections.abc import multiprocessing import os @@ -992,17 +993,21 @@ def test_run_checks_raises(self): """ Teardown functions are run when run_checks() raises SystemCheckError. """ - with mock.patch( - "django.test.runner.DiscoverRunner.setup_test_environment" - ), mock.patch("django.test.runner.DiscoverRunner.setup_databases"), mock.patch( - "django.test.runner.DiscoverRunner.build_suite" - ), mock.patch( - "django.test.runner.DiscoverRunner.run_checks", side_effect=SystemCheckError - ), mock.patch( - "django.test.runner.DiscoverRunner.teardown_databases" - ) as teardown_databases, mock.patch( - "django.test.runner.DiscoverRunner.teardown_test_environment" - ) as teardown_test_environment: + with ( + mock.patch("django.test.runner.DiscoverRunner.setup_test_environment"), + mock.patch("django.test.runner.DiscoverRunner.setup_databases"), + mock.patch("django.test.runner.DiscoverRunner.build_suite"), + mock.patch( + "django.test.runner.DiscoverRunner.run_checks", + side_effect=SystemCheckError, + ), + mock.patch( + "django.test.runner.DiscoverRunner.teardown_databases" + ) as teardown_databases, + mock.patch( + "django.test.runner.DiscoverRunner.teardown_test_environment" + ) as teardown_test_environment, + ): runner = DiscoverRunner(verbosity=0, interactive=False) with self.assertRaises(SystemCheckError): runner.run_tests( @@ -1016,18 +1021,22 @@ def test_run_checks_raises_and_teardown_raises(self): SystemCheckError is surfaced when run_checks() raises SystemCheckError and teardown databases() raises ValueError. """ - with mock.patch( - "django.test.runner.DiscoverRunner.setup_test_environment" - ), mock.patch("django.test.runner.DiscoverRunner.setup_databases"), mock.patch( - "django.test.runner.DiscoverRunner.build_suite" - ), mock.patch( - "django.test.runner.DiscoverRunner.run_checks", side_effect=SystemCheckError - ), mock.patch( - "django.test.runner.DiscoverRunner.teardown_databases", - side_effect=ValueError, - ) as teardown_databases, mock.patch( - "django.test.runner.DiscoverRunner.teardown_test_environment" - ) as teardown_test_environment: + with ( + mock.patch("django.test.runner.DiscoverRunner.setup_test_environment"), + mock.patch("django.test.runner.DiscoverRunner.setup_databases"), + mock.patch("django.test.runner.DiscoverRunner.build_suite"), + mock.patch( + "django.test.runner.DiscoverRunner.run_checks", + side_effect=SystemCheckError, + ), + mock.patch( + "django.test.runner.DiscoverRunner.teardown_databases", + side_effect=ValueError, + ) as teardown_databases, + mock.patch( + "django.test.runner.DiscoverRunner.teardown_test_environment" + ) as teardown_test_environment, + ): runner = DiscoverRunner(verbosity=0, interactive=False) with self.assertRaises(SystemCheckError): runner.run_tests( @@ -1041,18 +1050,19 @@ def test_run_checks_passes_and_teardown_raises(self): Exceptions on teardown are surfaced if no exceptions happen during run_checks(). """ - with mock.patch( - "django.test.runner.DiscoverRunner.setup_test_environment" - ), mock.patch("django.test.runner.DiscoverRunner.setup_databases"), mock.patch( - "django.test.runner.DiscoverRunner.build_suite" - ), mock.patch( - "django.test.runner.DiscoverRunner.run_checks" - ), mock.patch( - "django.test.runner.DiscoverRunner.teardown_databases", - side_effect=ValueError, - ) as teardown_databases, mock.patch( - "django.test.runner.DiscoverRunner.teardown_test_environment" - ) as teardown_test_environment: + with ( + mock.patch("django.test.runner.DiscoverRunner.setup_test_environment"), + mock.patch("django.test.runner.DiscoverRunner.setup_databases"), + mock.patch("django.test.runner.DiscoverRunner.build_suite"), + mock.patch("django.test.runner.DiscoverRunner.run_checks"), + mock.patch( + "django.test.runner.DiscoverRunner.teardown_databases", + side_effect=ValueError, + ) as teardown_databases, + mock.patch( + "django.test.runner.DiscoverRunner.teardown_test_environment" + ) as teardown_test_environment, + ): runner = DiscoverRunner(verbosity=0, interactive=False) with self.assertRaises(ValueError): # Suppress the output when running TestDjangoTestCase. diff --git a/tests/transactions/models.py b/tests/transactions/models.py index 9506bace351..3d4c7d7e449 100644 --- a/tests/transactions/models.py +++ b/tests/transactions/models.py @@ -6,6 +6,7 @@ commit-on-success behavior. Alternatively, you can manage the transaction manually. """ + from django.db import models diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py index 89dfd0deba4..8384f55b3c5 100644 --- a/tests/urlpatterns_reverse/tests.py +++ b/tests/urlpatterns_reverse/tests.py @@ -1,6 +1,7 @@ """ Unit tests for reverse URL lookups. """ + import pickle import sys import threading diff --git a/tests/urls.py b/tests/urls.py index 7d3a3a790ae..67c4d4091b4 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -3,5 +3,4 @@ This helps the tests remain isolated. """ - urlpatterns = [] diff --git a/tests/utils_tests/test_datastructures.py b/tests/utils_tests/test_datastructures.py index 07229f25ed9..d5d90b68fc0 100644 --- a/tests/utils_tests/test_datastructures.py +++ b/tests/utils_tests/test_datastructures.py @@ -1,6 +1,7 @@ """ Tests for stuff in django.utils.datastructures. """ + import collections.abc import copy import pickle diff --git a/tests/utils_tests/test_jslex.py b/tests/utils_tests/test_jslex.py index ee13eb4d64e..59551930c6f 100644 --- a/tests/utils_tests/test_jslex.py +++ b/tests/utils_tests/test_jslex.py @@ -1,4 +1,5 @@ """Tests for jslex.""" + # originally from https://bitbucket.org/ned/jslex from django.test import SimpleTestCase diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py index 65f9db89bfe..e1d7d296545 100644 --- a/tests/view_tests/tests/test_debug.py +++ b/tests/view_tests/tests/test_debug.py @@ -332,14 +332,19 @@ def test_template_loader_postmortem(self): with tempfile.NamedTemporaryFile(prefix=template_name) as tmpfile: tempdir = os.path.dirname(tmpfile.name) template_path = os.path.join(tempdir, template_name) - with override_settings( - TEMPLATES=[ - { - "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [tempdir], - } - ] - ), self.assertLogs("django.request", "ERROR"): + with ( + override_settings( + TEMPLATES=[ + { + "BACKEND": ( + "django.template.backends.django.DjangoTemplates" + ), + "DIRS": [tempdir], + } + ] + ), + self.assertLogs("django.request", "ERROR"), + ): response = self.client.get( reverse( "raises_template_does_not_exist", kwargs={"path": template_name}